假设我们有这四个类:
在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,这就是我想要的。
那么,我该怎么做呢?
编辑:
纠正了一些错误并重构了这个问题,我希望现在更清楚了。
答案 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
。如果希望将方法调用分派到最派生类型,则必须覆盖该方法,即在最派生类中提供具有相同精确签名的方法。