2011-01-08 2 views
4

Допустим, у нас есть эти четыре класса:Как можно повторно использовать функцию базового класса в производном классе

  • BinaryTree,
  • расширяющееся дерево (который является подклассом BinaryTree)
  • 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, который является тем, что я хочу.

Итак, как я могу это сделать?

EDIT:

Исправлены некоторые ошибки и переработан на вопрос, то я надеюсь, что это яснее.

+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. Если вы хотите, чтобы вызов метода отправлялся на наиболее производный тип, вы должны переопределить метод, который предоставляет метод с той же точной сигнатурой в самом производном классе.

Смежные вопросы