覆盖虚函数返回类型不同且在数据结构中不是协变的

Posted

技术标签:

【中文标题】覆盖虚函数返回类型不同且在数据结构中不是协变的【英文标题】:overriding virtual function return type differs and is not covariant in Data Structure 【发布时间】:2020-01-29 18:20:16 【问题描述】:

当我尝试编译时,我收到一个奇怪的错误:“覆盖虚函数返回类型不同且不是协变的”,我认为问题出在 Node.js 上。我觉得BTree<T>::NodeBSTree<T>::Node不一样。

基类:

#ifndef BINARY_TREE_H
#define BINARY_TREE_H

template < typename T >
class BTree 
protected:
    struct Node 
        T key;
        Node* left;
        Node* right;

        Node() 
        Node(
            const T& key,
            Node* left = nullptr,
            Node* right = nullptr)
            : left(left), right(right), key(key) 
    ;
public:
    BTree();
    virtual ~BTree();
    virtual Node* search(const T& key);


private:
    Node* search(const T& key, Node* root);

private:
    Node* root;
;

template < typename T >
typename BTree<T>::Node* BTree<T>::search(const T& key, BTree<T>::Node* root) 

    //some code


template < typename T >
typename BTree<T>::Node* BTree<T>::search(const T& key) 
    return search(key, root);


#endif // BINARY_TREE_H

派生类:

#ifndef BINARY_SEARCH_TREE_H
#define BINARY_SEARCH_TREE_H

#include "binary_tree.h"

template < typename T >
class BSTree : public BTree<T> 
protected:
    struct Node 
        T key;
        Node* left;
        Node* right;

        Node() 
        Node(
            const T& key,
            Node* left = nullptr,
            Node* right = nullptr)
            : left(left), right(right), key(key) 
    ;
public:
    BSTree();
    ~BSTree() override;  
    Node* search(const T& key) override;

private:
    Node* search(const T& key, Node* root);

private:
    Node* root;
;

template < typename T >
typename BSTree<T>::Node* BSTree<T>::search(const T& key, BSTree<T>::Node* root) 
    //some code


template < typename T >
typename BSTree<T>::Node* BSTree<T>::search(const T& key) 
    return search(key, root);


#endif // BINARY_SEARCH_TREE_H

【问题讨论】:

#define __BINARY_TREE__ 该标识符保留给语言实现。您应该使用另一个标头保护。 为什么要在BSTree 中重新定义Node 【参考方案1】:

虽然BSTree&lt;T&gt; 派生自BTree&lt;T&gt;,但BSTree&lt;T&gt;::NodeBTree&lt;T&gt;::Node 之间没有关系。因此,指向后者的指针不能转换为指向前者的指针。 BTree&lt;T&gt;::search 返回指向 BTree&lt;T&gt;::Node 的指针。因此,派生类中对该函数的任何覆盖都必须返回一个指针,该指针可转换BTree&lt;T&gt;::Node*

如前所述,BSTree&lt;T&gt;::Node* 不是。

真的,如果BSTree&lt;T&gt;::NodeBTree&lt;T&gt;::Node 做同样的事情,为什么还要存在?

【讨论】:

我无法访问 BTree::Node,我不知道为什么,这就是我再次写 struct Node 的原因, "我无法访问 BTree::Node" 那么你应该修复那个问题。你应该问一个单独的问题,提供无法编译的确切代码。【参考方案2】:

这是正确的代码。在看到BTree&lt;T&gt;::Node之前请小心添加typename

基类:

#ifndef BINARY_TREE_HPP
#define BINARY_TREE_HPP

template < typename T >
class BTree 
protected:
    struct Node 
        int key;
        Node* left;
        Node* right;

        Node() 
        Node(
            const int& key,
            Node* left = nullptr,
            Node* right = nullptr)
            : left(left), right(right), key(key) 
    ;
public:
    BTree();
    virtual ~BTree();    
    virtual Node* search(const T& key);

private:
    Node* search(const T& key, Node* root);

private:
    Node* root;
;

template < typename T >
typename BTree<T>::Node* BTree<T>::search(const T& key, BTree<T>::Node* root) 

    // some code


template < typename T >
typename BTree<T>::Node* BTree<T>::search(const T& key) 
    return search(key, root);

派生类:

#ifndef BINARY_SEARCH_TREE_HPP
#define BINARY_SEARCH_TREE_HPP

#include "binary_tree.hpp"

template < typename T >
class BSTree : public BTree<T> 
public:
    BSTree();
    ~BSTree() override;
    typename BTree<T>::Node* search(const T& key) override;

private:
    typename BTree<T>::Node* search(const T& key, typename BTree<T>::Node* root);

private:
    typename BTree<T>::Node* root;

;

template < typename T >
typename BTree<T>::Node* BSTree<T>::search(const T& key, typename BTree<T>::Node* root) 

    // some code


template < typename T >
typename BTree<T>::Node* BSTree<T>::search(const T& key) 
    return search(key, root);

【讨论】:

以上是关于覆盖虚函数返回类型不同且在数据结构中不是协变的的主要内容,如果未能解决你的问题,请参考以下文章

C++笔记之多态

C++笔记之多态

C++笔记之多态

C++从入门到入土第十八篇:多态

C++从入门到入土第十八篇:多态

理解多态的语法使用以及多态的实现原理