我正在通过在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;
}
}
}
答案 0 :(得分:2)
此处错误:
Node* Set::findSmallest(Node* node){
是因为Node
在用作返回类型时尚未在范围内。您应该写
Set::Node* Set::findSmallest(Node* node){
相反。或者,使用现代功能,
auto Set::findSmallest(Node* node) -> Node* {
答案 1 :(得分:1)
那里有两个语法问题:
像在开始时一样声明类Node不会被引用为Set :: Node类型。类名Set类内部的Node与它外部的Node不同。
您可以在findSmallest声明之前声明Node类
您需要指定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;
}