对于迭代器和类似情况,应如何处理“无效的协变量返回类型”

亚伯拉罕·穆尔西亚诺·本扎登

我正在尝试制作一个继承自的二进制树类Tree和搜索树的二进制类,以及每个继承自的嵌套类BSTTreeiteratorBST::iteratorTree::iterator

现在的问题是,一些树的功能必须返回iterator自己的类,如begin()end()search(T)等,这似乎不能编译,因为Tree::begin()BST::begin()有‘无效的协变返回类型’。

在研究了上述主题之后,我了解了导致编译器抱怨的原因,但是我不明白为什么不允许这样做例如,在这种情况下,Tree应该返回类型的对象Tree::iteratorBST应该返回类型的对象似乎是合乎逻辑的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;
};

BST小时

#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;

};

对我来说很明显,在这种情况下,搜索试图返回a BST<T>::iterator,而这是不允许的,因为它覆盖了返回a的函数Tree<T>::iterator,但是在我看来应该允许这样做,并且我不确定如何应该做到这一点。

另外,当BST<T>继承begin()and时end(),我假设它继承了它们,以便它们返回Tree<T>::iterators,尽管它们确实应该返回BST<T>::iterators

我到底想念的是什么?应该如何实现?

贾罗德42

多态只能通过指针/引用来完成,允许返回对象的协方差会引入切片。

我们既不能向“无关”类型添加协方差关系作为智能指针。(而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
};

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章