“不完全类型”在具有与该类本身相同类型的成员的类中

发布于 2024-11-15 13:57:07 字数 164 浏览 3 评论 0原文

我有一个类应该有同一个类的私有成员,例如:

class A {
    private:
        A member;
}

但它告诉我该成员是不完整的类型。为什么?如果我使用指针,它不会告诉我类型不完整,但我宁愿不使用指针。任何帮助表示赞赏

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

温柔女人霸气范 2024-11-22 13:57:07

在声明成员时,您仍在定义A 类,因此类型A 仍未定义。

但是,当您编写 A* 时,编译器已经知道 A 代表类名,因此“指向 A 的指针”类型已定义。这就是为什么您可以嵌入指向您定义的类型的指针。

同样的逻辑也适用于其他类型,因此如果您只编写:

class Foo;

您声明了类 Foo,但从未定义它。您可以写:

Foo* foo;

但不能写:

Foo foo;

另一方面,如果编译器允许递归定义,您期望类型 A 的内存结构是什么?

然而,有时在逻辑上,有一个类型以某种方式引用同一类型的另一个实例是有效的。人们通常使用指针来实现此目的,甚至更好:智能指针(如 boost::shared_ptr)以避免手动删除。

像这样的东西:

class A
{
  private:
    boost::shared_ptr<A> member;
};

At the time you declare your member, you are still defining the A class, so the type A is still undefined.

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.

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;

But not:

Foo foo;

On another hand, what memory structure would you expect for your type A if the compiler allowed a recursive definition ?

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.

Something like:

class A
{
  private:
    boost::shared_ptr<A> member;
};
尐偏执 2024-11-22 13:57:07

这是您想要实现的目标的一个工作示例:

class A {
public:
    A() : a(new A()) {}
    ~A() { delete a; a = nullptr; }
private:
    A* a;
};

A a;

Happy Stack Overflow!

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!

无人问我粥可暖 2024-11-22 13:57:07

A 在其定义结束之前是“不完整的”(尽管这不包括成员函数的主体)。

原因之一是,在定义结束之前,无法知道 A 有多大(这取决于成员大小的总和,加上其他一些因素)。您的代码就是一个很好的例子:您的类型 A 由类型 A 的大小定义。

显然,A 类型的对象不能包含也是A 类型的成员对象。

你必须存储一个指针或引用;想要存储其中任何一个都可能是可疑的。

A is "incomplete" until the end of its definition (though this does not include the bodies of member functions).

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.

Clearly, an object of type A may not contain a member object that is also of type A.

You'll have to store a pointer or a reference; wanting to store either is possibly suspect.

于我来说 2024-11-22 13:57:07

理解类 A 不完整的原因的一个简单方法是尝试从编译器的角度来看待它。

除此之外,编译器必须能够计算 A 对象的大小。了解大小是一个非常基本的要求,在许多情况下都会出现,例如在自动内存中分配空间、调用运算符 new 以及评估 sizeof(A) 。但是,计算 A 的大小需要知道 A 的大小,因为 aA 的成员。这会导致无限递归。

编译器处理这个问题的方法是认为A不完整,直到完全知道它的定义。您可以声明对不完整类的指针和引用,但不允许声明值。

A simple way to understand the reason behind class A being incomplete is to try to look at it from compiler's perspective.

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.

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.

℉服软 2024-11-22 13:57:07

您不能在 A 中包含 A。如果您能够这样做,并且您声明了,例如 A a;,则您需要引用 a.member.member.member。 .. 无限。您没有那么多可用内存。

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.

jJeQQOZ5 2024-11-22 13:57:07

A 类 的实例如何也包含A 类 的另一个实例?

如果需要的话,它可以保存指向 A 的指针。

How can an instance of class A also contain another instance of class A?

It can hold a pointer to A if you want.

许仙没带伞 2024-11-22 13:57:07

当您尝试使用尚未完全定义的类时,会发生此类错误。

尝试使用 A* 成员 代替。

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.

寂寞笑我太脆弱 2024-11-22 13:57:07

当编译器在代码中遇到 A 的对象时,就会出现问题。
编译器会搓手并开始创建 A 的对象。在这样做时,它将看到 A 有一个同样是 A 类型的成员。因此,为了完成 A 的实例化,它现在必须实例化另一个 A ,并且在这样做必须实例化另一个 A 等等。您可以看到它将以无限制的递归结束。因此这是不允许的。编译器在开始实例化类的对象之前,确保它知道所有成员的所有类型和内存需求。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文