[英]why compiler is saying Incomplete type error in this code?
#include<iostream.h>
class A
{
A a;
};
int main()
{
A a;
return 0;
}
为什么编译器说“ a”具有不完整的类型? 但是在Java中会发生递归..plz解释。
在C ++中, A a
表示类型A
的对象,而不是指向位于其他位置的某个对象的引用或指针。 必须知道A
的定义才能做出这样的陈述,除其他外,这意味着必须完全确定A
的大小。
当您尝试将某个类型的实例作为同一类型的成员时,您将获得无限递归。 该语言只是禁止这样做,指出任何类型的数据成员都必须是完整类型 ,这意味着其定义必须可用。
另一方面,这是允许的,并且更接近于Java语义:
class A { A* a; };
class B { B& b; };
有关更多信息,请参见此相关文章: 何时使用前向声明?
两者不相等。 在Java中命名对象时,实际上是在命名引用,因此C ++中的等效代码为:
class A
{
A& a;
};
或者,可以说:
class A
{
A* a;
};
这些都是完全有效的。
另一方面,尝试存储类型A
的值显然是行不通的。 Java根本没有语法甚至可以尝试这样做,但是C ++确实有-且不完整的类型规则会阻止您陷入其中。
在C ++中,您需要一个与该类处于同一类型的成员。这是不允许的,因为您需要知道对象的大小才能创建分配它的内存布局,并且它可能会如下所示:
- what's the size of A?
- it contains an object of class A.. what's the size of this object?
- what's the size of A?
- it contains.. bla bla bla
并且您最终将获得无限的递归而没有任何意义。 那是不允许的。 您可以使用引用或指针解决问题,但这与您要求的解决方案不同。
在Java中,允许使用语法,因为它不实例化类型(它是一个引用 ),但是如果您尝试实例化,则行为是相同的
public class myClass {
private myClass p = new myClass(); // Runtime error!!
public static void main(String[] args) {
new myClass();
}
}
需要注意的一件事:Java不会在编译时捕获它,而只会在运行时捕获(因此耗尽VM的内存,除非在此之前未检测到该机制),而C ++设法在编译时捕获它。
如果我们使用C ++标准草案,则可以看到直到结束}
才完全定义一个类,这在9.2
类成员第2段中:
在classspecifier的结尾},类被视为完全定义的对象类型(3.9)(或完整类型)。 [...]
并且一个类的所有非静态数据成员必须完整,这在第9段中:
非静态(9.4)数据成员不应具有不完整的类型。 特别地,类C不应包含类C的非静态成员,但可以包含对类C的对象的指针或引用。
但是正如它所说的,它可以包含一个指针或一个引用,它与Java的实现方式更为接近。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.