I like nested classes in C++. They allow a nicely fine grained approach to naming. Where a class may need to be called
CRegistryKeyIterator if declared at namespace level it can be called
Iterator if nested inside the
CRegistryKey class. The problem is I think I tend to overuse the feature…
I’m restructuring some code at present. This involves decoupling the IO Completion Port code for async IO from the socket server code in The Server Framework so that it can be used for file IO as well as network IO. The socket server had an IOPool class nested inside it. It probably shouldn’t have been structured that way.
I guess it all comes down to how ‘free standing’ a concept is. The
IOPool class isn’t really dependant on the
CSocketServer class in any way. The socket server uses the
IOPool but other people may wish to use the
IOPool without using the socket server… Whereas with the
CRegistryKeyIterator it’s less likely that you’d use the iterator without the key… I’d noticed a slight smell when using the
IOPool how when I wanted to provide a derived
IOPool class that provided debug information on IO pool events I had to include all of the socket server stuff. The derived IO pool didn’t need to know or care about the socket server yet the nested nature of the classes required it to pull in the socket server header to get access to the IO pool.
CIOBuffer has a nested
Allocator class, some parts of the code just care about the allocator and never need to access the buffer class. They’d get by with a header that defined the
Allocator and simply forward declared the buffer. Due to the nested nature of the class they can’t do that and become dependant on the buffer and changes to it even though they shouldn’t be.
As these concepts are moved from the socket tools library to the new library these knots are being untangled. I can’t help thinking that they’re the kind of knots that I’d never have tied if I’d been developing the code test first; they’re the kind of things that make it hard to test the code because writing a mock object to replace one of the concepts is out of the question.
I still think nested classes are useful, but I think I should be more careful about when I use them…