-2

In C++: assume I have a class X. Is there any difference between private inheritance like this:

class Deriv : private X
{
public:

//constructor etc

void method()
{
    usageOfMethodFromX();
}

};

and this:

class Deriv
{
private:
X * m_xinstance;

public:

//constructor etc

void method()
{
     m_xinstance->usageOfMethodFromX();
}

};

Is there any difference that does not allow substitute private inheritance with having a member of derived class and vice versa? Is this the same?

Thanks!

user1781713
  • 177
  • 7
  • The short answer is no. Private inheritance is a "has-a" relationship, which is the same relationship you get with a member variable. – Zac Howland Jan 02 '14 at 21:11
  • @ZacHowland: not quite: even when privately inheriting from a base with `virtual` member functions these members can be overridden! – Dietmar Kühl Jan 02 '14 at 21:16
  • Deriving allows you to take advantage of base subobject layout optimizations. – Kerrek SB Jan 02 '14 at 21:16
  • Don't understand the downvotes here. This is a perfectly legitimate question for someone with little knowledge of C++ to ask. And by "little" I mean less than 5 years spent learning every facet of the guargantuan language that is C++. – wheaties Jan 02 '14 at 21:16
  • 1
    @wheaties: I didn't downvote (nor do I plan to) but I'd guess the downvotes are for the question being a duplicate... – Dietmar Kühl Jan 02 '14 at 21:18
  • @DietmarKühl you're right! – wheaties Jan 02 '14 at 21:19
  • @DietmarKühl True, but since you don't have access to any of the private member data when you override the function, it is no different than having a function in `Derived` that does something itself. An example is found [here](http://stackoverflow.com/a/2158275/529761). – Zac Howland Jan 02 '14 at 21:21
  • @ZacHowland: I think it is reasonable to assume that `Derived` and/or `X` would call a `virtual` member if there is such a member. Thus, the behavior of the base class can be changed by further deriving from `Derived` when private inheritance is used. The same is not true when the `X` object is embedded or referenced from the `Derived`. – Dietmar Kühl Jan 02 '14 at 21:25
  • @DietmarKühl I'm not sure I follow you there. What I was saying is that if you overrode some function `Base::foo()`, you would have no access to any of `Base`'s member variables, so you would be doing nothing different than what you couldn't do with some `Derived::bar()`. You would basically just be preventing `Base::foo()` from being called unless you called it explicitly. – Zac Howland Jan 02 '14 at 21:31
  • @ZacHowland: Have a look at my answer: if `Base` (or a further derived class overriding `do_f()`) is embedded into `Derived`, the behavior of `do_f()` cannot be changed. When [privately] inheriting the bevior _can_ be changed. There is no need to look at any data members. The difference may not matter but deriving opens up the possibility for changes being introduced from further derived classes which can be prevented with embedding the object instead. – Dietmar Kühl Jan 02 '14 at 21:36
  • I am wondered that downgraded question had raised such constructive discussion ;) No, that post did not answered to my question well. This does. Thank you guys. – user1781713 Jan 02 '14 at 21:50
  • @user1781713: I agree that the "duplicate" linked to had nothing to do with the question you posted (I'd guess it is still a duplicate of something asked before, though). – Dietmar Kühl Jan 02 '14 at 21:55

3 Answers3

2

There is a subtle difference in case your base class has a virtual function: even if the base class is inherited privately, it can be overridden:

#include <iostream>
class Base {
    virtual int do_f() { return 1; }
public:
    int f() { return this->do_f(); }
};
class Derived: Base {
    int do_f() { return 2; }
public:
    int g() { return this->f(); }
};
class Final: public Derived {
    int do_f() { return 3; }
};

int main() {
    Final final;
    std::cout << final.g() << '\n';
}

The above code will print 3 (live example).

Another difference in your code is that the approach allocating memory, well, allocates memory on heap. You can avoid this heap allocation by embedding the object into your derived object.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
0

Yes.

In the inheritance model, the lifetime of the two objects is intertwined. A number of methods are automatically connected by default (operator=, constructors, destructors) and others may be in the future (operator swap aka :=:, =default other operators like < or ==). On top of this, virtual method overriding and calling can route calls to pointers to your parent interface (which you can provide others, or can be invoked by calling your parent methods) back to you.

If you replace your X * m_xinstance with X m_xinstance things get closer to being the same. Lifetime is now tied, and many (all?) of the hooked up methods are now hooked up similarly. virtual behavior is also very different.

A final difference is that if your base class is empty, the empty base class optimization can occur in one case, but not the member instance. As different objects must have different addresses, a member of your class has a minimum size of 1, while an empty base class can take up zero memory.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • You cannot use `dynamic_cast` nor `static_cast` to cast a derived class to a pointer to a base class (under private inheritance). - [Example](http://ideone.com/dX6G1M). – Zac Howland Jan 02 '14 at 21:29
0

There is a very significant and clear-cut difference: Consider this X:

class X {
  protected:
    void doSmth();
};

Only classes inheriting from X will have access to any and all protected members (here X::doSmth()).

bitmask
  • 32,434
  • 14
  • 99
  • 159
  • This in no way answers any of his questions ... – Zac Howland Jan 02 '14 at 21:21
  • @ZacHowland: No? Well, the OP's question was whether or not there is a difference between privately inheriting from a class `X` or adding a private member of it to a type. The answer is yes: It makes a tremendous difference if `X` has protected member that you wish to access from the "inheriting" class, because if you only have a member you're not allowed to access its protected members. – bitmask Jan 02 '14 at 21:31
  • You cannot access protected members of a base class in a derived class that is privately inherited, either. – Zac Howland Jan 02 '14 at 21:32
  • @ZacHowland: Are you sure? http://ideone.com/vSkTL9 – user1781713 Jan 02 '14 at 22:03
  • @user1781713 Perhaps I was unclear or misunderstood what was being said. Calling it from within the derived class is valid. I meant you could not call it `Derived d; d.doSmth();` Though, I remember discussions a while back about the ability to call protected methods in a privately inherited class being an oversight and not really having a use case. – Zac Howland Jan 02 '14 at 23:20
  • @ZacHowland: It massively has a usecase. If you use types as mixins, you can inherit privately from them and have them do redundant work for you. In that scenario, you *will* access the members of the derived type from within the deriving type's context. Which was precisely my point. To be honest, I'd say this is the primary thing you would be interested in doing with a privately inherited type (besides lifting restrictions on particular members with `using`). And don't tell me it's a misuse of inheritance, I know that; But it's useful at times. – bitmask Jan 03 '14 at 02:30