3

Consider a code

struct X {
    X (int n) {...}
};

struct Base {
    Base(X & x) {...}
};

struct Derived : public Base {
    Derived() : Base(x), x(2) {}
    X x;
};

Code works and i see no issue there but i'm concerned about the look of : Base(x), x(2) statement. First pass the instance to Base and after you initialize the actual object. Is this the the only way to express the intention?

Peter Silon
  • 457
  • 2
  • 11

1 Answers1

4

The trick is to derived from one more base class who's function is to own the X.

Note that base class declaration order matters:

struct X {
    X (int n) {}
};

struct Base {
    Base(X & x) {}
};

struct OwnsAnX {
    OwnsAnX(int n) : x_(n) {}

    X& get_x() { return x_; }
private:
    X x_;
};

struct Derived 
: OwnsAnX   // note: order is important
, Base 
{
    Derived() 
    : OwnsAnX(2)
    , Base(get_x()) 
    {}

    // x is accessed through the inherited get_x()
};

but it's error prone if you don't keep the correct order of the classes you're inheriting from

This is a valid concern of the OP. The solution is to enable the compiler warning -Wreorder.

Reversing the order of the base classes then yields:

<source>: In constructor 'Derived::Derived()':
<source>:24:23: warning: base 'OwnsAnX' will be initialized after [-Wreorder]
         , Base(get_x())
                       ^
<source>:24:23: warning:   base 'Base' [-Wreorder]
<source>:22:9: warning:   when initialized here [-Wreorder]
         Derived()
         ^~~~~~~
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
  • Definitely an option but it's error prone if you don't keep the correct order of the classes you're inheriting from. I'm still considering that this problem is best solved by `register(X * x)` method in Base class. – Peter Silon Apr 04 '17 at 18:38
  • @PeterSilon ordering is always a factor in inheritance and initialisation. You must do as you see fit. – Richard Hodges Apr 04 '17 at 20:56