I expect plenty of pitch-fork bearing purists who tend to align themselves with the crowd of goto is bad, and overloaded operators are bad to not like what I'm about to suggest. But; as with goto and overloaded operators, like certain medicines, too much can be fatal. I believe programmers can make reasonable decisions to the use of these constructs.
With Objective-C 2.0 came properties. These allowed for easy integration with key-value coding; but there's one problem with it - all properties are public. All methods are public as well. I believe this is bad programming style.
Here's a key to my solution; simple and elegant:
template<class T>
class Auto
{
private:
T m_o;
public:
inline T operator=(T in_o)
{
if (in_o) [in_o retain];
if (m_o) [m_o release];
m_o = in_o;
return m_o;
}
inline T noRetain(T in_o)
{
if (m_o) [m_o release];
m_o = in_o;
return m_o;
}
inline T operator()() const
{
return m_o;
}
inline Auto(T in_o = NULL)
: m_o(NULL)
{ (*this) = in_o; }
inline Auto(const TNS<T> &in_cpy)
: m_o(NULL)
{
(*this) = in_cpy();
}
inline ~Auto()
{
if (m_o) [m_o release];
}
};
Consider how this code nicely takes an an Objective-C object and wraps it in a smart-pointer. Ensuring that objects get retained and released becomes much more trivial - and a lot less typing. No need to define a parameter, synthesize, and double-check that it exists in the dealloc. Why? Objective-C++ automagically calls the destructor for C++ objects.
Using this is quite simple: Auto<NSString*> m_something; creates your string. Assign an auto-release string to it (or use the noRetain method) and off you go forgetting about this object. Assign a new string? The old one gets automatically released. Need to call a method? [m_something() UTF8String]; is a good example.
The good thing? minimal overhead - the compiler should inline out most, if not all, of the Auto object. What you're left with are the retains and releases that you'd have normally put in.
A note of caution: only use this object in places where you'd normally ensure an object gets a retain or release. Do not enthusiastically put it everywhere. Recall: good things in great quantities might not be that good. They can even be fatal!
On the up-side, if you want properties, you'll need to actually write the methods behind to translate from the C++ wrapper. This is good, you'll see, since it makes it harder to make objects publicly accessible, always a good design decision.
Before I wrap up this post; for private methods, I suggest using C static functions in your implementation files. Can't get more private than that!
For protected functions - useful with polymorphism - I'd avoid them. Once a function is declared, it can easily be reflected and used. No matter how hidden/private it is (unfortunately). I believe that this poses interesting software design constraints though.
No comments:
Post a Comment