2011-01-08 53 views
4

比方說,我們有這四個類:我如何能在派生類中重用基類功能

  • 二叉樹,
  • 伸展樹(這是一個子類二叉樹的),
  • BinaryNode和
  • SplayNode(它是BinaryNode的子類)。

在類BinaryTree中我有這2個函數,而在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 
{ 
    //... 
} 

,問題是當我有伸展樹的一個實例,我稱之爲查找,二進制:: Find2被調用,而不是伸展樹:: Find2,這就是我想要的。

那麼,我該怎麼做呢?

編輯:

糾正了一些錯誤,並重構了quetion,我希望這是更清晰了。

+1

您接受的答案並不是解決您的實際問題,而是一種不同的設計方法。實際的問題是由於不同的參數集合,'SplayTree :: Find2'不是'BinaryTree :: Find2'的重載。 C++不允許在覆蓋函數中使用協變參數(只有協變返回)。 –

回答

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。

2

您面臨的問題是SplayTree::Find2不是BinaryTree::Find2的覆蓋,而是一個不同的重載(即同時隱藏原始函數)。之所以說它是一個不同的函數是C++有協變返回類型的支持,而不是方法的參數,從而

BinaryTree一級調用Find2需要Node<T>類型的參數,併爲僅覆蓋這種方法是BinaryTree::Find2。如果要將方法調用分派到最派生類型,則必須重寫該方法,即在大多數派生類中提供具有相同確切簽名的方法。