返回值类型与函数类型不匹配(返回类型是嵌套类)

时间:2020-04-18 22:51:02

标签: c++ class scope binary-search-tree definition

我正在通过在C ++中实现集合数据结构来练习编程。我目前正在收到与函数的返回类型相关的编译器错误,该错误与函数的声明中所指示的不同。如果我注释掉set.cpp底部定义的Set::findSmallest,程序将编译。

我尝试了将hpp和cpp文件中的Node称为Set :: Node或仅称为Node的多种变体,但是我似乎无法使其正常工作。

我可以通过不将Node类嵌套在Set类内部来解决此问题,但我想练习使用嵌套类。

set.cpp:86:12: error: out-of-line definition of 'findSmallest' does not match any
      declaration in 'Set'
Node* Set::findSmallest(Node* node){
           ^~~~~~~~~~~~
./set.hpp:12:24: note: type of 1st parameter of member declaration does not match
      definition ('Node *' vs 'Set::Node *')
    Node* findSmallest(Node* node);
                       ^
set.cpp:90:20: error: cannot initialize return object of type 'Node *' with an lvalue of
      type 'Set::Node *'
            return nextNode;
                   ^~~~~~~~
2 errors generated.

set.hpp

#pragma once

class Node;

class Set{
public:
    Set();
    Set(int x);
    void find(int x);
    void insert(int x);
    Node* findSmallest(Node* node);
private:
    class Node {
    public:
        int value;
        Node *smallerNode;
        Node *greaterNode;
        Node();
        Node(int x);
    };
    Node* rootNode;
    Node* nextNode;
};

set.cpp

#include <iostream>
#include "set.hpp"

using std::cout;
using std::endl;

Set::Node::Node():value(0){
    smallerNode = nullptr;
    greaterNode = nullptr;
}
Set::Node::Node(int x):value(x){
    smallerNode = nullptr;
    greaterNode = nullptr;
}

Set::Set(){
    rootNode = nullptr;
    nextNode = nullptr;
}
Set::Set(int x){
    rootNode->value = x;
    nextNode = nullptr;
}

void Set::find(int x){
    nextNode = rootNode;
    while(1){
        if(x == nextNode->value){
            cout << x << " found!" << endl;
            return;
        }
        else if(x > nextNode->value){
            if(nextNode->greaterNode){
                nextNode = nextNode->greaterNode;
            }
            else {
                cout << x << " not found!" << endl;
                return;
            }
        }
        else {
            if(nextNode->smallerNode){
                nextNode = nextNode->smallerNode;
            }
            else {
                cout << x << " not found!" << endl;
                return;
            }
        }
    }
}
void Set::insert(int x){
    if(!rootNode){
        rootNode = new Node(x);
        return;
    }
    nextNode = rootNode;
    while(1){
        if(x == nextNode->value){
            cout << x << " already exists!" << endl;
            return;
        }
        else if(x > nextNode->value){
            if(nextNode->greaterNode){
                nextNode = nextNode->greaterNode;
            }
            else { 
                nextNode->greaterNode = new Node(x);
                cout << "inserted " << x << endl;
                return;
            }
        }
        else {
            if(nextNode->smallerNode){
                nextNode = nextNode->smallerNode;
            }
            else {
                nextNode->smallerNode = new Node(x);
                cout << "inserted " << x << endl;
                return;
            }
        }
    }
}

Node* Set::findSmallest(Node* node){
    Node* nextNode = node;
    while(1){
        if(!nextNode->smallerNode){
            return nextNode;
        }
        else {
            nextNode = nextNode->smallerNode;
        }
    } 
}

4 个答案:

答案 0 :(得分:2)

此处错误:

Node* Set::findSmallest(Node* node){

是因为Node在用作返回类型时尚未在范围内。您应该写

Set::Node* Set::findSmallest(Node* node){

相反。或者,使用现代功能,

auto Set::findSmallest(Node* node) -> Node* {

答案 1 :(得分:1)

那里有两个语法问题:

  1. 像在开始时一样声明类Node不会被引用为Set :: Node类型。类名Set类内部的Node与它外部的Node不同。

  2. 您可以在findSmallest声明之前声明Node类

  3. 您需要指定Set :: Node *作为返回类型

//class Node; <- remove this

class Set{
public:

    class Node {
    public:
        int value;
        Node *smallerNode;
        Node *greaterNode;
        Node();
        Node(int x);
    };

    Set();
    Set(int x);
    void find(int x);
    void insert(int x);
    Node* findSmallest(Node* node);

private:

    Node* rootNode;
    Node* nextNode;
};

在cpp文件中:

Set::Node* Set::findSmallest(Node* node){
    ...

答案 2 :(得分:1)

要添加到@numzero的答案,您在findSmallestNode的声明之前声明Node,这将给您带来错误。

您需要在定义Node之后定义函数,或在Node中转发声明Set。请注意,在类外的Node声明不会在类内向前声明Node

答案 3 :(得分:1)

此前向声明

class Node;

是冗余的,并且与类Set的定义中的成员类Node的声明不同。

class Node;

class Set{
public:
    Set();
    Set(int x);
    void find(int x);
    void insert(int x);
    Node* findSmallest(Node* node);
private:
    class Node {
    //...

因此,实际上您声明了两个类Node。一个在全局名称空间中,另一个作为类Set的成员。

在类Set定义中,名称Node在这些声明中指代类成员Node

Node *smallerNode;
Node *greaterNode;

但是在类定义之外(例如,在此声明中)

Node* Set::findSmallest(Node* node){
//..

声明者findSmallest(Node* node)之前的名称Node指的是在全局命名空间中声明的名称。另一方面,在声明器中用作参数类型的名称Node指的是在Set范围类中声明的名称Node。

只需删除转发声明

class Node;

不使用。

在引用它之前,您需要定义Node类。因此,可以通过以下方式重新格式化类定义

class Set{
private:
    class Node {
    public:
        int value;
        Node *smallerNode;
        Node *greaterNode;
        Node();
        Node(int x);
    };
    Node* rootNode;
    Node* nextNode;

public:
    typedef class Node Node;

    Set();
    Set(int x);
    void find(int x);
    void insert(int x);
    static Node* findSmallest(Node* node);
};

请注意,因为findSmallest函数将指向节点的指针作为参数接受,然后应将其声明为静态成员函数。在这种情况下,可以通过以下方式定义

Set::Node* Set::findSmallest( Node *node )
{
    if ( node != nullptr )
    {
        while ( node->smallerNode ) node = node->smallerNode;
    }

    return node;
}    

否则,在类定义中应将其声明为

Node* findSmallest() const;

并在类外定义,例如

Set::Node* Set::findSmallest() const
{
    Node *node = rootNode;

    if ( node != nullptr )
    {
        while ( node->smallerNode ) node = node->smallerNode;
    }

    return node;
}    

还要注意这个构造函数

Set::Set(int x){
    rootNode->value = x;
    nextNode = nullptr;
}

具有未定义的行为,因为指针rootNode尚未初始化。

和数据成员

Node* nextNode;

是多余的,应将其删除。在某些成员函数中,它用作局部辅助变量。因此,应在这些函数中定义此类变量。

函数查找不得输出任何消息。它是函数的调用者决定是否输出消息。该函数应具有返回布尔值,并声明为常量成员函数。

例如

bool find(int x) const;

类外函数的定义可以遵循以下方式

bool Set::find( int x ) const
{
    Node *node = rootNode;

    while ( node != nullptr && node->value != x )
    {
        if ( x < node->value ) node = node->smallerNode;
        else node = node->greaterNode;
    }

    return node != nullptr;
}