When I want to add functionality to this structure, without changing it:
class MemberBase
{
public:
virtual MemberBase* clone() const;
virtual void action1();
...
}
class Container
{
public:
virtual void functionUsingAction1();
...
private:
std::vector<MemberBase*> members_
}
I can subclass MemberBase and
class MemberType1 : public MemberBase
{
public:
MemberBase* clone() const;// Reimplementation
void action1(); // Reimplementation
virtual void action2(); // New functionality
}
I can fill the container with the desired type of data by employing the
MemberBase* MemberBase::clone() const;
Method. But how do I call
void MemberType1::action2();
from the methods of the Container class? I can use dynamic_cast, but that is considered a design flaw. Is there any workaround? Or better, any pattern I can follow?
Honestly, the more I look at it and it looks like a typical Visitor application to me.
I would suggest avoiding implementing any intelligence in your
Containerclass, and instead delegate the actions to a specificVisitorclass. The baseVisitorcan be given some way to safely interact with the underlying container structure (erase/insert).Then you need to implement the member’s
acceptmethods. It’s purely mechanical.And finally you can implement a visitor:
And you use it as:
The weakness of this design is that a new
visitmethod need be implemented for each new class directly deriving fromMemberBase, and thus theMemberBasehierarchy is not so open. This can be alleviated using the Acyclic Visitor; however, I have rarely needed it.To “extend” the ability, you can have
Visitor::visitandMemberBase::acceptreturn an “action” to be executed (erase, clone, etc…) and deal with this in the two loops you actually have. It could be reduced to one loop using some tricks…