Search code examples
c++virtual-inheritance

C++17 initializing base class constructor using drived class constants as the paramers of the base class constructor


Now before i continue with the question i would like to state i have read that that const values, references must be initialized in the initialization list of the constructor. However i still need clarification in this case.

Here is a realy simple inheritance example with code attached https://github.com/courteous/constrcutorChaining

class F : E

class E : D

class D : C

class C : B

class B : A

The only spcecific part here is that base class "A" inherits publicly from a template "enable_shared_from_this"

Now the different behavior i observe is i.e. when I create a share pointer of "E" then the "parameterized D constructor called : 17" is being called

shared_ptr<E> eInstance = make_shared<E>();

default A constructor called
default B constructor called
default C constructor called
parameterized D constructor called : 5
default E constructor called

however if i create a shared pointer of class F like that

shared_ptr<F> fInstance = make_shared<F>();

default A constructor called
default B constructor called
default C constructor called
default D constructor called
default E constructor called
default F constructor called

then the default E constructor is called Why is that in this case.

I have found other answers in Stackoverflow that refere to the problem of the copy constructor not beein implemented i.e.

Default constructor called instead of parametrized constructor

but in this case no cloning or coping is beeing done i.e. a simple base constructor explicitelly called.

The expected behavior here should be that the parameterized class D constructor should always be called, but that is not the case when I create a shared pointer of F. Can someone tell me why and what would be the right approach toforce class F to take the path F-> "default constructor" E->"default constructor " ->"parameterized D constructor called : 17".

The interesting classes in this case are F, E and D

F.h

#ifndef _F_
#define _F_

#include "E.h"

#include <string>
#include <memory>

namespace constructroTest
    {

    class F : public virtual E {


    public:
        static const uint16_t fixedLength;

        explicit F();
        virtual ~F();

protected:
        shared_ptr<F> shared_from_this()
            {
            return dynamic_pointer_cast<F>(E::shared_from_this());
            }
        };

    }


#endif  //#ifndef _F_

E.h

#ifndef _E_
#define _E_

#include "D.h"

#include <string>
#include <memory>

namespace constructroTest
    {

    class E : public virtual D
        {

    public:
        static const uint16_t fixedLength;

        explicit E();
        virtual ~E();

protected:
        shared_ptr<E> shared_from_this()
            {
            return dynamic_pointer_cast<E>(D::shared_from_this());
            }
        };

    }

#endif  //#ifndef _E_

D.h

#ifndef _D_
#define _D_

#include "C.h"
#include <string>
#include <memory>


namespace constructroTest
    {

    class D : public virtual C
        {


    public:
        static const uint16_t fixedLength;


        explicit D();
        virtual ~D();


        explicit D(uint16_t dArgument);


protected:
        shared_ptr<D> shared_from_this()
            {
            return dynamic_pointer_cast<D>(C::shared_from_this());
            }
        };

    }


#endif  //#ifndef _D_

Solution

  • In case of virtual inheritance, only the most derived class initializes the virtual base class.

    So in

    shared_ptr<E> eInstance = make_shared<E>();
    

    virtual base D is build from E

    Whereas, in

    shared_ptr<F> eInstance = make_shared<F>();
    

    virtual base D is build from F ("ignoring" E).