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) {}