Thursday, August 23, 2007
Pay it Forward: Part 2
When writing C++ classes and interfaces (e.g. abstract classes), do your compiler a favor and declare each class in its own header file whenever you can. Trust me, it'll pay you back later.
Rule of thumb:
Now, here's an example of how not to use your nested types:
... actually no. You can get on with your life. Your incremental build is now done because you've paid it forward!
Rule of thumb:
If you ever need to use the would-be nested class without using the nesting class, then your class should not be nested.To see how nested classes should be used, look at std::string::iterator. It's a nested type (Okay, okay, it could be a nested typedef that could alias a non-nested class. From outside std::string, it looks like a nested class and that's all that matters.) that's useless without its nesting class std::string.
Now, here's an example of how not to use your nested types:
AddressBook.h
// Forward type declarationWith the the above implementation, whenever someone wants to receive notification from the AddressBook, they need to include the AddressBook itself and derive from AddressBook::IContactEventSink. Doing this has the following down sides:
class Contact; // Remember this?
class AddressBook
{
public:
// Interface to be implemented by objects wanting AddressBook notifications.
class IContactEventSink
{
public:
virtual void onContactChanged(Contact const& oldContact, Contact const& newContact) = 0;
};
...
};
- Your IContactEventSink interface is now coupled with the AddressBook class. What if you want to re-use IContactEventSink for your CorporateAddressBook class?
- You won't be able to forward-declare the IContactEventSink class because nested classes can't be forward declared (See Pay it Forward - Part 1 for why you'd want to do this).
- Every time anything changes in the AddressBook.h file, you'll have to waste time rebuilding all files using the IContactEventSink.
IContactEventSink.h
// Forward type declarationThen, hit "Build", sit back and wait to...
class Contact; // Yup, even here.
class IContactEventSink
{
public:
virtual void onContactChanged(Contact const& oldContact, Contact const& newContact) = 0;
};
... actually no. You can get on with your life. Your incremental build is now done because you've paid it forward!
Labels: c++, compiler, nested class, pay it forward