C++ 具有与类本身相同类型的成员的类中的“不完整类型”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6349822/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"Incomplete type" in class which has a member of the same type of the class itself
提问by Sterling
I have a class that should have a private member of the same class, something like:
我有一个类应该有同一个类的私有成员,例如:
class A {
private:
A member;
}
But it tells me that member is an incomplete type. Why? It doesn't tell me incomplete type if I use a pointer, but I'd rather not use a pointer. Any help is appreciated
但它告诉我成员是一个不完整的类型。为什么?如果我使用指针,它不会告诉我不完整的类型,但我宁愿不使用指针。任何帮助表示赞赏
回答by ereOn
At the time you declare your member, you are still definingthe A
class, so the type A
is still undefined.
在你宣布你的会员的时候,你还在定义的A
类,这样的类型A
仍然是不确定的。
However, when you write A*
, the compiler already knows that A
stands for a class name, and so the type "pointer to A" is defined. That's why you can embed a pointer to the type your are defining.
但是,当你写A*
,编译器已经知道A
代表一个类名,所以输入“指针A”的定义。这就是为什么您可以嵌入指向您正在定义的类型的指针的原因。
The same logic applies also for other types, so if you just write:
同样的逻辑也适用于其他类型,所以如果你只写:
class Foo;
You declare the class Foo, but you never define it. You can write:
您声明了类 Foo,但从未定义过它。你可以写:
Foo* foo;
But not:
但不是:
Foo foo;
On another hand, what memory structure would you expect for your type A
if the compiler allowed a recursive definition ?
另一方面,A
如果编译器允许递归定义,您希望类型的内存结构是什么?
However, its sometimes logically valid to have a type that somehow refer to another instance of the same type. People usually use pointers for that or even better: smart pointers (like boost::shared_ptr
) to avoid having to deal with manual deletion.
但是,有时具有某种以某种方式引用同一类型的另一个实例的类型在逻辑上是有效的。人们通常为此使用指针,甚至更好:智能指针(如boost::shared_ptr
)以避免必须处理手动删除。
Something like:
就像是:
class A
{
private:
boost::shared_ptr<A> member;
};
回答by Nick
This is a working example of what you are trying to achieve:
这是您要实现的目标的工作示例:
class A {
public:
A() : a(new A()) {}
~A() { delete a; a = nullptr; }
private:
A* a;
};
A a;
Happy Stack Overflow!
堆栈溢出快乐!
回答by Lightness Races in Orbit
A
is "incomplete" until the end of its definition (though this does not include the bodies of member functions).
A
在其定义结束之前是“不完整的”(尽管这不包括成员函数的主体)。
One of the reasons for this is that, until the definition ends, there is no way to know how large A
is (which depends on the sum of sizes of members, plus a few other things). Your code is a great example of that: your type A
is defined by the size of type A
.
这样做的原因之一是,在定义结束之前,无法知道有多大A
(这取决于成员大小的总和,再加上其他一些因素)。您的代码就是一个很好的例子:您的类型A
由 type 的大小定义A
。
Clearly, an object of type A
may not contain a member object that is also of type A
.
显然,一个 type 的对象A
可能不包含一个也是 type 的成员对象A
。
You'll have to store a pointer or a reference; wanting to store either is possibly suspect.
您必须存储指针或引用;想要存储任何一个都可能是可疑的。
回答by dasblinkenlight
A simple way to understand the reason behind class A
being incomplete is to try to look at it from compiler's perspective.
理解类A
不完整背后原因的一种简单方法是尝试从编译器的角度来看它。
Among other things, the compiler must be able to compute the size of A
object. Knowing the size is a very basic requirement that shows up in many contexts, such as allocating space in automatic memory, calling operator new
, and evaluating sizeof(A)
. However, computing the size of A
requires knowing the size of A
, because a
is a member of A
. This leads to infinite recursion.
除此之外,编译器必须能够计算A
对象的大小。知道大小是一个非常基本的要求,它出现在许多上下文中,例如在自动内存中分配空间、调用 operatornew
和评估sizeof(A)
。但是,计算 的大小A
需要知道 的大小A
,因为a
是 的成员A
。这导致无限递归。
Compiler's way of dealing with this problem is to consider A
incomplete until its definition is fully known. You are allowed to declare pointers and references to incomplete class, but you are not allowed to declare values.
编译器处理这个问题的方法是考虑A
不完整,直到它的定义完全已知。您可以声明对不完整类的指针和引用,但不允许声明值。
回答by mah
You cannot include A within A. If you were able to do that, and you declared, for example, A a;
, you would need to refer to a.member.member.member...
infinitely. You don't have that much RAM available.
您不能在 A 中包含 A。如果您能够做到这一点,并且您声明了,例如,A a;
,您将需要a.member.member.member...
无限引用。你没有那么多可用的内存。
回答by Andrei
How can an instance of class A
also contain another instance of class A
?
一个实例如何class A
也包含另一个实例class A
?
It can hold a pointer to A if you want.
如果需要,它可以保存指向 A 的指针。
回答by trema
This type of error occurs when you try to use a class that has not yet been fully DEFINED.
当您尝试使用尚未完全定义的类时,会发生此类错误。
Try to use A* member
instead.
尝试使用A* member
。
回答by Sushovan
The problem happens when the compiler comes across an object of A in code. The compiler will rub its hand and set out make an object of A. While doing that it will see that A has a member which is again of type A. So for completing the instantiation of A it now has to instantiate another A ,and in doing so it has to instantiate another A and so forth. You can see it will end up in a recursion with no bound. Hence this is not allowed. Compiler makes sure it knows all types and memory requirement of all members before it starts instantiating an object of a class.
当编译器在代码中遇到 A 的对象时,就会出现问题。编译器将揉搓手并开始创建 A 的对象。在这样做时,它将看到 A 有一个也是 A 类型的成员。因此,为了完成 A 的实例化,它现在必须实例化另一个 A ,并且在这样做它必须实例化另一个 A 等等。您可以看到它将以无限制的递归结束。因此这是不允许的。编译器在开始实例化一个类的对象之前,确保它知道所有成员的所有类型和内存要求。