C ++: design, function template override and no polymorphism
They have a base class A and a derived class B that overrides the Func functional pattern:
class A
{
A() {...};
~A() {};
template <class T>
void Func(const String &sInput, T &tResult)
{...}
};
class B : public A
{
B() {...}
~B() {};
template <class T>
void Func(const String &sInput, T &tResult)
{...}
};
(Note that Func is not virtual given the lack of support in C ++ for templated virtual functions.)
Now you have API mainprog, class M:
class M
{
M(boost::shared_ptr<A> &pInterfaceInput): pInterface(pInterfaceInput)
{}
template <class T>
Evaluate(const String &sInput, T &tResult)
{
pInterface->Func<T>(sInput, tResult);
}
private:
const boost::shared_ptr<A> pInterface;
};
I want the Evaluate function here to support function calls in base class A or any of its derived classes (such as B). This class was written with polymorphism in mind before I reworked classes A and B to have templated functions.
Now the problem is that if I pass a generic base type pointer to a derived type, then the base class Func will be called, not the derived class it points to.
How do I get around the lack of dynamic polymorphism? I considered creating a class template class M for a generic pointer type and having a static_cast in the constructor to ensure that the type is of the base class (A) or derived class type.
What's the best way to do this? I would prefer not to change classes A and B to get around this issue, but all suggestions are appreciated.
Thank.
Sounds like a double dispatch problem . Perhaps this would be a good place to implement the pattern
For example, create a class Evaluator
and for each T
subclass ConcreteEvaluator<T>
. Give methods A
and B
who attend Evaluator
. Something like:
class Evaluator
{
virtual void visit_A(A* object);
virtual void visit_B(B* object);
};
template <typename T>
class ConcreteEvaluator : public Evaluator
{
public:
String* input_reference;
T& result_reference;
ConcreteEvaluator(String& input_reference_,T& result_reference_) :
input_reference(input_reference_),
result_reference(result_reference_) {}
virtual void visit_A(A* object) {
object->Func(input_reference,result_reference);
}
virtual void visit_B(B* object) {
object->Func(input_reference,result_reference);
}
}
class A
{
...
virtual void apply_evaluator(Evaluator *eval) {eval->visit_A(this);}
...
}
class B
{
...
virtual void apply_evaluator(Evaluator *eval) {eval->visit_B(this);}
...
}
For each subclass A
to ConcreteEvaluator
have to be added to the new method, so this method works best if the class hierarchy A
is stable. And for each subclass, A
it must have a specific function apply_evaluator
.
On the other hand, it can be a complete excess. For about the same amount of work, you can always just pay the price to upgrade M::Evaluate
:
class M
{
...
void Evaluate(const String& sInput, T& tResult)
{
// try to downcast to each subclass of A. Be sure to check
// sub-subclasses first
try
{
dynamic_cast<B*>(pInterface.get())->Func(sInput, tResult);
return;
}
catch (std::bad_cast& ) { }
...
// nothing worked. It must really be an A
pInterface->Func(sInput,tResult);
}
...
};
source to share
I am showing in the question Templatized Virtual function how to use type erasure to get some of the effects of a virtual member function. Depending on what you want to do in Func (), you can use the same technique here.
source to share