有一个基类A和一个派生类B,它覆盖了函数模板Func:
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)
{...}
};
(请注意,Func是非虚拟的,因为C ++中缺少对模板化虚拟函数的支持。)
现在有一个mainprog API,类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;
};
我希望此处的Evaluate函数支持对基类A或其任何派生类(如B)上的函数的调用。在重新设计A类和B类以具有模板化函数之前,这个类在编写时考虑了多态性。
现在的问题是,如果我将基类型的共享指针传递给派生类型,那么将调用基类的Func,而不是指向的派生类。
如何解决这里缺乏动态多态性的问题? 我已经考虑将类M作为共享指针类型的类模板,并在构造函数中使用static_cast来确保此类型是基类类型(A)或派生类。
最好的方法是什么?我不想修改A类和B类以解决这个问题,但欢迎提出所有建议。
感谢。
答案 0 :(得分:3)
听起来像double dispatch问题。也许这是实施visitor pattern的好地方?
例如,创建一个类Evaluator
,并为每个T
创建一个子类ConcreteEvaluator<T>
。提供访问A
的{{1}}和B
方法。类似的东西:
Evaluator
对于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);}
...
}
的每个子类,必须在A
中添加一个新方法,以便在ConcreteEvaluator
的类层次结构稳定时,此方法最有效。对于A
的每个子类,它必须正确定义A
函数。
另一方面,这可能是完全矫枉过正。对于大约相同数量的工作,您可以随时付出代价来更新apply_evaluator
:
M::Evaluate
答案 1 :(得分:1)
我在问题Templatized Virtual function中展示了如何使用类型擦除来获得虚拟成员函数的一些效果。根据你在Func()中想要做的事情,你可以在这里使用相同的技术。