Original Post
I'm in the process of updating certain sections of my code base, using, in part, Scott Meyers' excellent "Effective C++ - 3rd Edition" book.
However, I am a little confused with Item 39 in the book, which says, and quite rightly too, to use private inheritance judiciously.
Cool... No problem there. I've rarely used such constructs myself and prefer the (usually more) superior design of composition to model the "is-implemented-in-terms-of" software design.
Nonetheless, Scott does give three cases in which private inheritance is justified, namely:
When a (privately) derived class needs access to protected base class members.
When a (privately) derived class needs to redefine inherited virtual functions.
Saving space using empty base optimization (EBO) which, in most circumstances, is perhaps the weakest case.
I have no issue with cases two and three but cases' one criterion could be easily met by simply using a mixture of composition and friendship.
I.e., to avoid code bloat and taking heed of Scott's wisdom on factoring parameter-independent code out of templates (Item 44), I designed an (implementation domain) object on the lines of:
Because I only want this class to implement all parameter-independent code of the templated class "Friend", I opted to make this class fully private and accessible to "Friend" instances only.
Then, in "Friend"'s class template definition, we deploy the following composition:
Using this approach which also has the added benefit of avoiding code bloat in templated classes, I personally don't see why using private inheritance is ever justified under the first case.
But then of course, in his defence, Scott did say to use only such constructs in rare cases. Still, I am a bit puzzled as to why he didn't mention using friends in situations as stipulated in case one... Any thoughts?
However, I am a little confused with Item 39 in the book, which says, and quite rightly too, to use private inheritance judiciously.
Cool... No problem there. I've rarely used such constructs myself and prefer the (usually more) superior design of composition to model the "is-implemented-in-terms-of" software design.
Nonetheless, Scott does give three cases in which private inheritance is justified, namely:
When a (privately) derived class needs access to protected base class members.
When a (privately) derived class needs to redefine inherited virtual functions.
Saving space using empty base optimization (EBO) which, in most circumstances, is perhaps the weakest case.
I have no issue with cases two and three but cases' one criterion could be easily met by simply using a mixture of composition and friendship.
I.e., to avoid code bloat and taking heed of Scott's wisdom on factoring parameter-independent code out of templates (Item 44), I designed an (implementation domain) object on the lines of:
class Object
{
// Friend class template declaration (see later!)
template<typename> friend class Friend;
// Fields
int itsMember;
// "Private" class
Object () {...}
~Object () {...}
// Other private methods defined here etc...
};
Because I only want this class to implement all parameter-independent code of the templated class "Friend", I opted to make this class fully private and accessible to "Friend" instances only.
Then, in "Friend"'s class template definition, we deploy the following composition:
template<typename T>
class Friend
{
// Fields
Object itsObject; // composition
// Other methods defined here etc...
};
Using this approach which also has the added benefit of avoiding code bloat in templated classes, I personally don't see why using private inheritance is ever justified under the first case.
But then of course, in his defence, Scott did say to use only such constructs in rare cases. Still, I am a bit puzzled as to why he didn't mention using friends in situations as stipulated in case one... Any thoughts?