如何在派生类中重用基类函数

时间:2011-01-08 14:23:22

标签: c++ templates inheritance polymorphism

假设我们有这四个类:

  • BinaryTree,
  • SplayTree(BinaryTree的子类),
  • BinaryNode和
  • SplayNode(BinaryNode的子类)。

在BinaryTree类中我有这两个函数,在SplayTree中我想重用第一个函数,因为它的工作方式与SplayTree相同。

//BinaryTree.cpp
bool Find(const T &data) const
{
    Node<T> *found = Find2(data, root); 
    //...
} 
virtual Node<T> * Find2(const T &data, Node<T> *node) const
{
    //...
}

//SplayTree.cpp
using BinaryTree::Find; 
virtual SplayNode<T> * Find2(const T &data, SplayNode<T> *node) const
{
    //...
}

现在,问题是当我有一个SplayTree实例并且我调用Find时,调用Binary :: Find2而不是SplayTree :: Find2,这就是我想要的。

那么,我该怎么做呢?

编辑:

纠正了一些错误并重构了这个问题,我希望现在更清楚了。

2 个答案:

答案 0 :(得分:4)

CRTP成语用于解决此类问题。基本上,您从一个模板派生,该模板将派生类作为模板参数,因此您可以在返回值等中使用该类型。

在您的实例中,您需要为两个树类型创建一个公共基础模板,并在那里实现Find,同时在派生类中实现Find2

template <class T> class BaseTree
{
public:
  bool Find()
  {
    typename T::NodeType* NodePtr = static_cast<T*>(this)->Find2(...);
  }
}

template <class T>
class BinaryTree<T> : public BaseTree<BinaryTree<T>>
{
public:
  typedef Node<T> NodeType;
  NodeType Find2(); // will be called from BaseTree
};

template <class T>
class SplayTree : public BaseTree<SplayTree<T>>
{
  typedef SplayNode<T> NodeType;
  NodeType Find2(); // dito
};

这基本上实现了'静态多态'。正常多态性的好处是你可以根据需要使用返回类型。

修改:添加了更详细的说明以更好地适应OP。

答案 1 :(得分:2)

您面临的问题是SplayTree::Find2不是BinaryTree::Find2的覆盖,而是一个不同的重载(同时隐藏原始函数)。它是一个不同的函数的原因是C ++支持协变返回类型,但不支持方法的参数,因此

BinaryTree级别,对Find2的调用采用Node<T>类型的参数,此类方法的唯一覆盖为BinaryTree::Find2。如果希望将方法调用分派到最派生类型,则必须覆盖该方法,即在最派生类中提供具有相同精确签名的方法。