Create an instance of a class in the class itself

2019-02-16 17:03发布

问题:

This question already has an answer here:

  • Can a c++ class include itself as an member? 4 answers

I am new to C++ and have a question:

Compare following code:

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

and

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

I know the second part of code can't pass compile. But I want to know the reason.

Is it related to memory allocation or just syntax regulation?

I would be appreciate if someone can solve my question.

回答1:

The code in your second fragment cannot compile, because the class Node is not completely defined at the point where you declare its data member x of Node type.

For the sake of understanding, imagine if it could compile, it would lead to some sort of "infinite recursion structure", that would take an infinite amount of memory. Here's the hypothetical layout of such a class object:

{
  data: int
  x: Node
  {
    data: int
    x: Node
    {
      data: int
      x: Node
      {
        ...
      }
    }
  }
}

The first case works because you do not need a class to be fully defined in order to declare a pointer to it.
I find that thinking of "fully defined" as "the compiler knows how big this class is" helps to reason about problems like this: the compiler needs to know how big a class is to declare an instance of it, but not to declare a pointer to it, which has the same size regardless of the class.



回答2:

If you could, then a Node would contain a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node, which contains a Node... and so on until the universe is full of Nodes and implodes.



回答3:

It's more related to basic logic. In order for Node to contain an object of the same size as itself, and something else, it would have to be larger than itself, or infinite in size.

The language also prevents it since the type is incomplete within its own definition (so you can't even have the degenerate case of an otherwise empty class containing itself). But that's rather incidental to the more fundamental logical impossibility.



回答4:

The compiler needs to know the complete type of A when it founds it inside class A. Because A is incomplete, it cannot determine its size, it cannot determine how much space the member variable a is going to take, therefore it will not compile it.



回答5:

To fix such a problem you could also give forward declaration a try. But the problem lies in what Martin J Already stated.

class Node;

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

bear in mind this is not tested