开发者

Private inheritance and composition, which one is best and why? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.

Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.

Closed 2 years ago.

Improve this question 开发者_如何学编程

suppose i have a class engin and i inherit a class car from engin class

class engin
{
    public:
        engin(int nobofcylinders);
        void start();
};
class car:private engin
{
    public:
        car():e(8){}
        void start()
        {
            e.start();
        }
    private:
        engin e;
};

now the same can be done by the composition, the question is which approch would be best and is mostly used in programming, and why???????


Composition is to be preferred for two main reasons:

  • the thing(s) being composed can have names
  • you can compose more than one thing of the same type


I prefer to think of inheritance as derived is a kind of base, that basically means public inheritance. In case of private inheritance it more like derived has a base, which IMHO doesn't sound right, because that's IMHO the work for composition not inheritance of any kind. So, since private inheritance and composition essentially mean same thing logically, which to choose? With the example you posted, I'd most certainly go for composition. Why? I tend to think of all kinds of inheritance as a kind of relationship, and with the example you posted, I can't think of a situation where I could say a car is kind of an engine, it simply isn't. It's indeed like a car has an engine, so why would a car inherit from an engine? I see no reason.

Now, indeed there are cases where it's good to have private inheritance, namely boost::noncopyable, with it's ctor/dtor being protected, you'd have hard time instantiating it, and indeed since we want our class to have a noncopyable part, that's the only way to go.

Some style guides (e.g. google c++ style guide) even recommend to never use private inheritance, for reasons similar to what I already written - private inheritance is just a bit confusing.


If you want to compare private inheritance with composition, read http://www.parashift.com/c++-faq-lite/private-inheritance.html#faq-24.3. I don't think private inheritance is good.


A Car has-an Engine, but a Car is-not-an Engine, so it should be better done with composition.

Inheritence is useful for "is-a" relationships, e.g. a Bus is-a Car, a Car is-a vehicle, etc.

Composition is useful for "has-a" relationships, e.g. a Car has Wheel-s, a Car has-an Engine, etc.

So a logical code should be like

class Car : public Vehicle {
    Engine engine;
    Wheel  wheels[4];
    ...
};


Private inheritance, despite the name, isn’t really inheritance – at least not from the outside (of the class), where it matters.

For that reason, different rules apply. In C++, private inheritance is said to model an “is implemented in terms of” relationship. Thus, a priority queue which is implemented in terms of a heap, could look like this:

template <typename T, typename Comp = std::less<T> >
class priority_queue : private heap<T, Comp> {
    // …
};

Personally, I don’t see the advantage of this pattern, and Neil has already stated that in most cases, composition actually has the advantage over private inheritance.

One advantage exists, though: since it’s such an established pattern, the meaning of a private inheritance is immediately clear to a seasoned C++ programmer; the above code would tell them that the priority queue is implemented in terms of a heap – which wouldn’t be obvious if the class just happened to use a heap as one of its members.

Private inheritance tends to get used in C++ primarily for policy classes. The classical example is allocators, which determine how a container class manages storage internally:

template <typename T, typename A = std::allocator<T> >
class vector : private A {
    // …
};

No harm done. But once again, this could also have been done using composition.


Usually, composition is to be preferred (others gave the major reasons), but private inheritance allows things which can't be done by composition:

  • zero-size base class optimization (a base class of size zero will not increase the size of a class, a member of size zero will), that't the reason behind its use for policy classes which often have no data members

  • controlling initialization order so that what is composed is initialized before a public base

  • overriding a virtual member in what is composed

  • with private virtual inheritance, ensuring that there is only one composed thing even if one do it in several bases

Note that for the later two uses, the fact that the base class exist can be observed in a descendant.


Composition is used more than private inheritance. The general rule I follow and would recommend is that unless you have a specific reason to use private inheritance you should use composition.

Composition has many benefits over private inheritance:

  • You can have more than one instance of a particular class.
  • You don't pollute your class' namespace with a bunch of private functions that don't make sense for your class.
  • You can give names to the parts of your object
  • Your class is less coupled to the classes it's composed of than it is to a class it inherits from
  • If you discover you need to swap out an object that you've included by composition during the lifetime of your object, you can, with private inheritance you're stuck.

There are a lot of other benefits to composition. Basically, it's more flexible and cleaner.

There are reasons to use private inheritance though. They are very specific reasons, and if you think they apply, you should think carefully about your design to make sure you have to do it that way.

  • You can override virtual functions.
  • You can get access to protected members of the base class.
  • You need to pass yourself to something that wants an object of the class you're inheriting from (this usually goes hand-in-hand with overriding virtual functions).

And there are a few rather tricky ones as well:

  • If you use composition for a class that has 0 size, it still takes up space, but with private inheritance it doesn't.
  • You want to call a particular constructor for a virtual base class of the class you're going to privately inherit from.
  • If you want to initialize the private base before other base classes are initialized (with composition, all the variables in your class will be initialized after all your base classes are).
  • Using private virtual inheritance to make sure there's only one copy of a thing even when you have multiple base classes that have it. (In my opinion, this is better solved using pointers and normal composition.)


  • Private inheritance means is-implemented-in-terms of. It's usually inferior to composition, but it makes sense when a derived class needs access to protected base class members or needs to redefine inherited virtual functions.

  • Unlike composition, private inheritance can enable the empty base optimization. This can be important for library developers who strive to minimize object sizes.

Scott Meyers "Effective C++" Third Edition.


Base classes are evil.

In my mind, good OO design is about encapsulation and interfaces. The convenience of base classes are not worth the price you pay.

Here's a really good article about this:

http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜