为什么编译器在这段代码中说不完整类型错误?

时间:2014-02-06 18:06:33

标签: c++

#include<iostream.h>

class A 
{    
   A a;            

};             

int main()       
{       

A a;              
return 0;           
}

为什么编译器说“a”的类型不完整? 但是在java递归中发生..plz解释它。?

4 个答案:

答案 0 :(得分:5)

在C ++中,A a表示类型为A的对象,而不是指向位于其他位置的某个对象的引用或指针。必须知道A的定义才能做出这样的陈述,除其他外,这意味着必须完全确定A的大小。

当您尝试将类型的实例作为相同类型的成员时,您将获得无限递归。该语言完全不允许这样做,声明任何类型的数据成员必须是完整类型,这意味着它的定义必须是可用的。

另一方面,这是允许的,并且更接近java语义:

class A { A* a; };
class B { B& b; };

有关详细信息,请参阅此相关帖子:When to use forward declaration?

答案 1 :(得分:2)

这两者并不相同。当您使用Java命名对象时,实际上是在命名引用,因此C ++中的等效代码是:

class A 
{    
   A& a;
};

或者,可以说:

class A 
{    
   A* a;
};

这些都非常有效。

另一方面,尝试存储A类型的显然不起作用。 Java只是没有语法来尝试这一点,但C ++确实 - 并且不完整类型规则阻止你陷入其中。

答案 2 :(得分:2)

在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 ++设法在编译时捕获它

答案 3 :(得分:1)

如果我们转到draft C++ standard,我们可以看到在结束}之前未完全定义某个类,这是在9.2 类成员部分中段落 2

  

在classspecifier的close}处,类被视为完全定义的对象类型(3.9)(或完整类型)。 [...]

并且类的所有非静态数据成员必须完整,在 9 段落中

  

非静态(9.4)数据成员不得有不完整的类型。特别是,C类不得包含   C类的非静态成员,但它可以包含指向C类对象的指针或引用。

但正如它所说它可以包含一个指针或一个更接近Java如何做的引用。