Home > OS >  Pass member of derived class into constructor of base class
Pass member of derived class into constructor of base class

Time:03-26

I have an abstract base class parent that owns an abstract base class child, and a corresponding derived parent that owns a derived child.

I want to be able to construct the derived child inside my derived parent's initialization, while also keeping a reference to the derived child itself - but this isn't straightforward. As I need to initialize the base first, I cannot pass in an already initialized reference to my derived child into the base's constructor.

I can dynamic_cast the base class' base pointer to my derived child back into a derived-type pointer to keep as a member, but this cannot be a sane approach. Is there a pattern for this kind of thing?

Ex.

This is what I'd like to be able to do, but obviously cannot:

DerivedParent::DerivedParent():
    _derivedChild:(new DerivedChild()),
    BaseParent:(_derivedChild)
{}

While this is what works, but obviously isn't sensible:

DerivedParent::DerivedParent():
    BaseParent:(new DerivedChild()),
    _derivedChild:(dynamic_cast<DerivedChild*>(_baseChild))
{}

Is there a pattern for this kind of thing, or am I doing something fundamentally silly?

CodePudding user response:

First and foremost, why do you need to do it ? If you need some properties from the base class, why not pass it to the constructor of the child ? Or mark the attributes as protected and access it in the child class ?

The base class should not know the child class. It's the O 'Open/Closed' principle of SOLID. That's means that every time you add a child class, you must change the base class.

So, the child should have everything it need to be initialized correctly.

CodePudding user response:

With BaseParent having a _baseChild member, your second solution of _derivedChild(dynamic_cast<DerivedChild*>(_baseChild)) is fine. Since you know the type will match, you can also use static_cast instead. In fact, since you know the dynamic type of _baseChild will always be DerivedChild, you can just replace this->_derivedChild in member functions with static_cast<DerivedChild*>(this->_baseChild) (maybe behind a getter function).

You can also use a delegating constructor to avoid the cast:

DerivedParent() : DerivedParent(new DerivedChild()) {}

private:
DerivedParent(DerivedChild* derivedChild) :
    BaseParent(derivedChild), _derivedChild(derivedChild) {}

  • Related