为什么编译器在此代码中说不完整的类型错误
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中发生递归..请解释一下。?
在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 段:
类在类说明符的结尾 } 处被视为完全定义的对象类型 (3.9)(或完整类型)。[...]
并且类的所有非静态数据成员都必须是完整的,即第 9 段:
非静态 (9.4) 数据成员不得具有不完整的类型。特别是,C类不应包含 类 C 的非静态成员,但它可以包含指向类 C 对象的指针或引用。
但正如它所说,它可以包含一个指针或引用,这将更接近 Java 的工作方式。
- 类没有命名C++代码中的类型错误
- 不完整类型错误(E0409、E0070、E0515)
- 使用具有结构不完整类型错误的模板
- 不命名构造函数和析构函数上的类型错误
- 返回派生类型时出现协变类型错误
- 为什么此构造函数没有给出不完整的类型错误?
- 定义模板化结构的特征时出现不完整的类型错误
- 使用重载构造函数时出现不完整的类型错误
- 为什么我得到表达式必须有类类型错误?
- 输出 [left]=input[i] 行中的 c++ 代码中存在无效的类型错误
- 枚举成员不是类型错误
- 如何修复"ctypes"。参数错误:参数 2:<键入"异常.类型错误">:RaspberryPi 中的错误类型"错误
- 外部 "C" Visual Studio 2015 中的显式类型错误,DLL 测试代码
- 非默认析构函数会导致不完整的类型错误
- 为什么按引用传入会导致绑定引用类型错误
- Objective-C C++ 包装器 类型错误的不完整定义
- 输入类型错误
- 当构造函数的参数类型错误时引发异常
- 命名空间中的'bad_cast' 'std' 未命名类型错误
- C UNWORKOWN类型错误