Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialize base class with data member from derived class [duplicate]

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?

like image 739
Peter Silon Avatar asked Oct 18 '25 15:10

Peter Silon


1 Answers

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()
         ^~~~~~~
like image 89
Richard Hodges Avatar answered Oct 20 '25 05:10

Richard Hodges