2016-08-16 18 views
-2

我知道在C++类型的递归定义的问题为成员变量:理解为函数的返回类型的“相互递归问题”

#include "B.h" 
class A 
{ 
    B b; 
}; 

#include "A.h" 
class B 
{ 
    A b; 
}; 

编译器抱怨这是因为以这种递归方式分配内存是不可能的。

我不明白的是,这似乎适用于函数的定义,以及:

#include "B.h" 
class A 
{ 
    B foo(); 
}; 

#include "A.h" 
class B 
{ 
    A bar(); 
}; 

编译器给出了同样的错误:

error: ‘A’ does not name a type 
error: ‘B’ does not name a type 

为什么就是它?编译器需要为返回类型保留空间对我来说没有意义。我应该用指针和前向声明来解决这个问题吗?根据我的经验(来自Java),程序员做这些递归定义来设计软件是很常见的。在C++中实现这一点似乎很难。

+0

是需要为返回值保留空间。 Java通过引用返回所有类对象。 –

+0

正向引用足以解决你的相互依赖关系。 – Jarod42

+0

我的问题不好?我想知道为什么有降薪。也许有人可以给我一些反馈,下次我可以改进。我会很感激。 – aeduG

回答

2

至于函数定义去,所有你需要的是一个适当的向前声明:

class A; 
class B; 

class A 
{ 
    B foo(); 
}; 

class B 
{ 
    A bar(); 
}; 

这将编译没有问题。随意将其分成两个单独的头文件,并使用适当的前向声明而不是#include

请注意,您不能以相同的方式声明类成员的原因是因为这将有效地包含一个类本身。不幸的是,如果这是可能的,最终的结果将是一个巨大的黑洞,将吞噬我们所知道的所有生命,并且我们当然不希望发生这种情况...我们肯定不希望发生这种情况...

无论如何,需要记住的是你受到Java背景的影响。尽管类似的语法非常类似,但C++在Java中的工作方式与Java的工作方式有着根本的不同。你最好忘记关于Java如何工作的一切。否则,你会继续下去,就像那样。在Java中,一组类似的声明不会导致有效地包含它自己的类,但是它在C++中有效。这是因为在Java中,每个类实例实际上都是指向类的指针,但在C++中,它是类本身,有血有肉。

在C++中,真正等同于这种递归类声明的是:

class A 
{ 
    std::shared_ptr<B> b; 
}; 

class B 
{ 
    std::shared_ptr<B> A; 
}; 

(暂时忽略必要的,在这里申请前向声明,太)。

这将在C++中工作,因为它在Java中工作(std::shared_ptr<>部分相当于Java的对象引用计数,排序)。 是相当于您在Java中的类似构造。

2

你需要一个向前声明

class B; // forward declaration 

class A 
{ 
    B foo(); 
}; 

class B 
{ 
    A bar(); 
}; 

声明上面告诉class B存在的编译器,但不是它是什么样子。这足以将其用作函数或方法的参数或返回类型。然后你可以跟进实际的定义。

+0

谢谢你的回答。我知道我可以用前向声明来解决它,但不知道它是否是正确的或最好的方法。如果你的代码被分割成不同的头文件,我想另一个“A类”在B类文件中需要 – aeduG

1

What I don't understand is that this seems to apply to function definitions as well:

函数可以被编译器内联,唯一的方法就是当你知道返回类型的确切布局时。 除此之外,编译器必须知道如何构造函数的返回类型


注:编译器并不需要知道一个函数声明的返回类型的完整定义,但是它确实需要在定义中了解它。

//file A.h 
class B; //forward declaration 

class A 
{ 
    B foo(); //declaration 
}; 

//file A.cpp 
#include "B.h" 

B A::foo(){ .... } //definition 

//file B.h 
class A; //forward declaration 
class B 
{ 
    A bar(); //declaration, works 
    A moo() { .... } //Declaration + Definition, Fails to see full definition of `A` 
}; 

//file B.cpp 
#include "A.h" 

A B::boo() { ... }