тип возвращаемого значения не соответствует типу функции (тип возвращаемого значения - вложенный класс) - PullRequest
0 голосов
/ 19 апреля 2020

Я занимаюсь программированием, реализуя заданную структуру данных в C ++. В настоящее время я получаю эту ошибку компилятора, связанную с тем, что тип возвращаемого значения функции отличается от того, что указано в ее объявлении. Программа компилируется, если я закомментирую Set::findSmallest, который определен в нижней части набора. cpp.

Я пробовал много вариантов ссылки на Node как Set :: Node или просто Node в hpp и cpp файлов, но я не могу заставить его работать.

Я могу решить эту проблему, не вкладывая класс 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 ]

2 голосов
/ 19 апреля 2020

Ошибка здесь:

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

из-за того, что Node еще не находится в области действия к тому времени, когда он используется в качестве возвращаемого типа. Вы должны написать

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

. Или, используя современную функцию,

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

1 голос
/ 19 апреля 2020

Это прямое объявление

class Node;

является избыточным и не совпадает с объявлением класса-члена Node в определении класса Set.

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 *smallerNode;
Node *greaterNode;

Однако вне например, определение класса в этом объявлении

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

имя узла перед декларатором findSmallest(Node* node) относится к имени, объявленному в глобальном пространстве имен. С другой стороны, имя Node, используемое в объявителе в качестве типа параметра, относится к имени Node, объявленному в классе Set scope.

Просто удалите прямое объявление

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 принимает в качестве аргумента указатель на узел, тогда она должна быть объявлена ​​как функция-член stati c. В этом случае он может быть определен следующим образом

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;

является избыточны и должны быть удалены. Он используется в качестве локальной вспомогательной переменной в некоторых функциях-членах. Таким образом, такая переменная должна быть определена в этих функциях.

Функция find не должна выводить никаких сообщений. Вызывающая функция решает, выводить ли сообщение. Функция должна иметь возвращаемый тип bool и быть объявлена ​​как постоянная функция-член.

Например,

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;
}    
1 голос
/ 19 апреля 2020

Чтобы добавить к ответу @ numzero, ваше объявление findSmallestNode предшествует определению Node, что приведет к ошибке.

Вам нужно либо определить функцию после определения Node, либо объявить вперед Node в Set. Обратите внимание, что объявление Node вне класса не вперед объявляет Node внутри класса.

1 голос
/ 19 апреля 2020

Существует две проблемы с синтаксисом c:

  1. Объявление класса Forward, как вы делаете в начале, не будет называться типом Set :: Node. Имя класса Node внутри класса Set не совпадает с Node вне его.

  2. вы можете объявить класс Node перед объявлением findSmallest

  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){
    ...
...