Skip to main content
GameDev.net gamedev.net
🔒 Locked

Private Inheritance v Composition

Started by CodeStorm May 14, 2012 at 1:11 PM 3 replies 2.3k views
Original Post
CodeStorm
CodeStorm
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:


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?
Telastyn
Telastyn

Still, I am a bit puzzled as to why he didn't mention using friends in situations as stipulated in case one... Any thoughts?


Because if the base class is already written, it's difficult/impossible to append the friendship to it.
alvaro
alvaro
I would stay away from private inheritance in all three (and any other) cases. To me private inheritance means that the fact that I derive from the base class is a detail of implementation that shouldn't concern anyone else. In that case, it is unclear to me whether the maintainer of the base class should be aware of the existence of this class, for instance.

  1. If I feel I need access to protected parts of the base class, chances are those parts need to be public.
  2. If I feel the need to redefine a virtual function, I probably need to rethink my design.
  3. I don't worry about 1 to 4 byte differences.

I only every use public inheritance, and only for the purpose of getting polymorphic behavior, where a factory function is the only one that knows about the multiple derived classes and the rest of the program only cares about the interface. Any uses beyond that (e.g., private, protected, virtual or multiple inheritance) seem too complicated to me and I don't want to have to maintain them, so I don't write them.

Of course if you are working on a team that has embraced all of those C++ features, you may not have the option to keep the code as C-like as mine.
CodeStorm
CodeStorm
Thanks guys... Very good points there.

I totally hear you alvaro! Inheritance generally sends shivers up my coding spine and the only place in which I've used inheritance thus far is in the design of abstract interfaces.

However, with regards to the code base, it's mine, so I only raised this point to determine the best way to go about redesigning some of my older code so, that said, I'll stick with friends and composition then.

But of course, private inheritance may raise it's ugly head in situations outlined by Telastyn so, it's always good to know these things in any case. tongue.png
Codarki
Codarki
Very very rarely. I think I once used it when I wanted to store bunch of objects into same container, without exposing common baseclass. Something like this: (made up example)

class device_child
{
protected:
device_child(device_child_collection& children);
~device_child();
};

class texture_2d : device_child
{
public:
texture_2d(device_child_collection& children)
: device_child(children)
{
}
};

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.