在类本身中创建类的实例 我是C++新手,有个问题:

在类本身中创建类的实例 我是C++新手,有个问题:,c++,declaration,C++,Declaration,比较以下代码: class Node { public: int data; Node* x; }; 及 我知道代码的第二部分无法通过编译。但我想知道原因 它是与内存分配有关,还是仅仅与语法规则有关 如果有人能解决我的问题,我将不胜感激。您的第二个片段中的代码无法编译,因为类节点在声明其节点类型的数据成员x时没有完全定义 为了理解,想象一下,如果它可以编译,它将导致某种“无限递归结构”,这将占用无限的内存。 下面是此类类对象的假设布局: { data: int x:

比较以下代码:

class Node { 
public:
    int data;
    Node* x;
};

我知道代码的第二部分无法通过编译。但我想知道原因

它是与内存分配有关,还是仅仅与语法规则有关


如果有人能解决我的问题,我将不胜感激。

您的第二个片段中的代码无法编译,因为类
节点
在声明其
节点
类型的数据成员
x
时没有完全定义

为了理解,想象一下,如果它可以编译,它将导致某种“无限递归结构”,这将占用无限的内存。 下面是此类类对象的假设布局:

{
  data: int
  x: Node
  {
    data: int
    x: Node
    {
      data: int
      x: Node
      {
        ...
      }
    }
  }
}
第一种情况之所以有效,是因为您不需要完全定义类来声明指向它的指针。

我发现,将“完全定义”理解为“编译器知道这个类有多大”有助于解释这样的问题:编译器需要知道一个类有多大才能声明它的一个实例,而不是声明指向它的指针,它的大小与类无关。

它与基本逻辑更相关。为了使
节点
包含与自身大小相同的对象以及其他对象,它必须比自身大,或者是无限大


由于类型在其自己的定义中是不完整的(因此,您甚至不能使用包含自身的空类的退化情况),因此语言也会阻止它。但这是更基本的逻辑不可能性的附带条件。

如果可以,那么
节点将包含
节点,其中包含
节点,其中包含
节点,其中包含
节点,其中包含
节点,其中包含
节点,其中包含
节点,其中包含
节点,其中包含
节点,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
,它包含一个
节点
。。。等等,直到宇宙充满了
节点
并内爆。

要解决这样的问题,你也可以尝试一下转发声明。 但问题在于Martin J已经说过的话

class Node;

class Node { 
public:
    int data;
    Node* x;
};

请记住,这是未经测试的

编译器在类A中找到A时需要知道A的完整类型。由于A不完整,它无法确定其大小,也无法确定成员变量A将占用多少空间,因此,它不会编译它。

编译器不必知道节点上的任何东西,就可以管理指向节点的指针。它至少部分与内存分配有关,因为
节点
实例的大小将由于递归而变为无穷大。每个实例将包含
节点
的所有变量以及
节点
的另一个实例,该实例将包含一个或多个实例,依此类推。最后,构造无法分配,因为它的大小是无限的。但是指针呢?我认为第一个案例可以通过编译并正确工作。@Oh2是的,它可以。(顺便说一句,如果你了解Java:它或多或少相当于Java版本的
类节点{public int data;public Node x;}
,因为在Java中,类类型的变量隐式地只是指针。)问题的正确可视化我已经看到了一整天的最佳答案。但是如果是无限的,这个世界怎么可能充满
节点呢?(它是无限的吗?你需要在回答中详细说明。)宇宙同时充满了
节点和一个
节点,这更可怕。@TonyD“我有鼻子”的说法并没有因为我也有肚脐而被证伪。但是指针呢?我认为第一种情况可以通过编译并正确工作。编辑答案以说明为什么它与指针一起工作。创建指向它的指针不必知道对象的大小,它只是一个地址,并且不“包含”任何内容。在声明指向
节点的指针时,这是不必要的,编译器已经知道它是一个类的名称,即使没有转发声明。不知道你是否已经删除了我的帖子。如果是,原因是什么?我已经说过它没有经过测试。我做了,因为我说了(你的答案虽然没有坏处,但没有帮助,也没有给现有的答案添加任何内容),部分原因是“没有测试”:D.当你不知道它是否有效时,你不应该给出答案(特别是对于这样一个简短且易于测试的答案)。我很抱歉,我真的不是故意粗鲁的。我之所以否决你的答案,是因为它没有回答这个问题,也不会帮助任何未来的读者(在OP的问题和你的例子中,转发声明是完全无用的)。您的示例之所以有效,是因为指针,所以转发声明可以是
class Node;

class Node { 
public:
    int data;
    Node* x;
};