0

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_
Jarod42
  • 203,559
  • 14
  • 181
  • 302
Tito
  • 2,234
  • 6
  • 31
  • 65
  • 1
    Unrelated to your problem, but please note that all symbols beginning with an underscore and followed by an upper-case letter (like e.g. `_D_`) are *reserved*. You should not define such symbols yourself. See e.g. [What are the rules about using an underscore in a C++ identifier?](https://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier) for more details. – Some programmer dude Jan 22 '20 at 09:29
  • thanks I will consider this ,, in fact very good point – Tito Jan 22 '20 at 09:31
  • For MCVE, you might get rid of A, B, C (). Provide constructor. (During minimization of example, you might also notice that `shared_from_this` stuff were unneeded) – Jarod42 Jan 22 '20 at 09:45
  • you are right A B and C are not needed in this case. I will cut them off. However i was not sure about shared_from_this thus included it ,, but can remove that as well. – Tito Jan 22 '20 at 09:47

1 Answers1

1

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).

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • thank you for the quick replay. What would be the right way to enforce the behavior where parameterized D constructor will be called even if virtual inheritance is used since the virtual inheritance is needed in my case not in the case of this example. – Tito Jan 22 '20 at 09:40
  • did you made a mistake by making bough instance " shared_ptr eInstance = make_shared(); " ? or was that deliberate? – Tito Jan 22 '20 at 09:42
  • @Tito: typo fixed -> `make_shared` not `E` in last case, – Jarod42 Jan 22 '20 at 09:43
  • is there a way to enforce the behavior of always calling the parameterized D constructor even if virtual inheritance is used ? – Tito Jan 22 '20 at 09:59
  • Jarod32 i am trying to follow here. I am confused why this is still happening if i am explicitly telling in Class F that it needs to call his base class i.e. "F::F() : E()" . If D is constructed from E the by calling the default constructor of E, D parameterized should get executed. – Tito Jan 22 '20 at 10:13
  • You need `F() : D(42), E() {}`. You might remove/`=delete` default `D` constructor to force to only use the constructor taking parameter. – Jarod42 Jan 22 '20 at 10:19