我正在尝试创建一个继承自Tree
的二进制树类BST
和一个二进制搜索树类Tree
以及嵌套的iterator
嵌套类每个,其中BST::iterator
继承自Tree::iterator
。
现在,问题在于某些树的函数必须返回其自身类的iterator
,例如begin()
,end()
,search(T)
等。由于Tree::begin()
和BST::begin()
具有“无效的协变量返回类型”,因此似乎无法编译。
研究了上述主题之后,我了解了导致编译器抱怨的原因,但我不明白为什么。例如,在这种情况下,Tree
应该返回类型为Tree::iterator
的对象,而BST
应该返回类型为BST::iterator
的对象似乎是合乎逻辑的。
下面是一些代码,应说明我正在处理的内容。
template <class T>
class Tree {
protected:
class Node {
friend Tree;
T value;
Node* left;
Node* right;
};
Node* root;
public:
class iterator {
friend Tree;
Node* node;
public:
// operators and the like...
};
virtual iterator begin() const;
virtual iterator end() const;
virtual iterator search(const T& value) const;
};
#include "Tree.h"
template <class T>
class BST : public Tree<T> {
protected:
class Node : public Tree<T>::Node {
friend BST;
};
using Tree<T>::root;
public:
class iterator : public Tree<T>::iterator {
friend BST;
};
using Tree<T>::begin;
using Tree<T>::end;
virtual iterator search(const T& value) const override;
};
对我来说很明显,在这种情况下,搜索试图返回一个BST<T>::iterator
,这是不允许的,因为它覆盖了一个返回Tree<T>::iterator
的函数,但是对我来说似乎合乎逻辑应该允许这样做,我不确定应该如何做。
此外,当BST<T>
继承begin()
和end()
时,我假设它继承了它们,使得它们返回Tree<T>::iterators
,尽管它们实际上应该返回{{1} }。
答案 0 :(得分:1)
多态只能通过指针/引用来完成,允许返回对象的协方差会引入切片。
我们不能将协方差关系添加到“无关”类型作为智能指针。 (而Base*
和Derived*
可以协变,std::unique_ptr<Base>
和std::unique_ptr<Derived>
不能:/)
协方差可以通过指针/引用来完成。
解决这些限制的一种方法是拥有2种方法,一种具有支持的协方差的虚拟方法,以及一种使用虚拟的方法模拟协方差的常规方法:
template <typename T>
class Tree {
// ...
// Assuming iterator might be constructed with node.
typename Tree<T>::iterator begin() const { return {node_begin()/*, ...*/}; }
typename Tree<T>::iterator end() const { return {node_begin()/*, ...*/}; }
protected:
virtual typename Tree<T>::node* node_begin() const;
virtual typename Tree<T>::node* node_end() const;
};
template <class T>
class BST : public Tree<T> {
// ...
typename BST<T>::iterator begin() const { return {node_begin()/*, ...*/}; }
typename BST<T>::iterator end() const { return {node_begin()/*, ...*/}; }
protected:
typename BST<T>::node* node_begin() const override; // covariance on pointer
typename BST<T>::node* node_end() const override; // covariance on pointer
};