C ++:设计,函数模板覆盖和缺乏多态性

时间:2009-09-06 11:56:19

标签: c++ inheritance oop

有一个基类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类以解决这个问题,但欢迎提出所有建议。

感谢。

2 个答案:

答案 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()中想要做的事情,你可以在这里使用相同的技术。