【发布时间】:2021-09-18 04:06:34
【问题描述】:
将以下代码视为 C++ Primer 5th Ed。第 7.6 节。
class Bar {
public:
// ...
private:
static Bar mem1; // ok: static member can have incomplete type --> Tag 1
Bar *mem2; // ok: pointer member can have incomplete type --> Tag 2
Bar mem3; // error: data members must have complete type --> Tag 3
int x=4; --> Tag 4
}
- 上面的类定义被认为是一个定义。这个调用定义没有像创建的对象那样分配存储。
- 标签 1 和 2 有效,因为 Bar 被视为声明。我对此很满意,因为没有创建类 Bar 的对象。这些是类定义中的声明。
- 标签 3 是我遇到问题的地方。对我来说,标签 3 被认为是声明,因为尚未创建类 Bar 的实例。
- 标签 4 - 在这个阶段我也会认为这是一个声明,因为没有创建类 Bar 的实例。
Point 是那些像标签 3 和 4 这样的数据成员,只有在类 Bar 的实例是在类定义之外创建时,我才会将它们视为定义。
Bar bar; --> this would then initialize tag 3 & 4 --> Tag 5
为什么标签 3 需要完整,因为在这一行没有分配存储,因为它仍然是一个声明?标记 3 还不是这一行的实例。当我们在类定义之外创建类 Bar 时,标签 3 仅成为一个定义并分配存储空间,就像在标签 5 中一样。
【问题讨论】:
-
Tag 3 需要完整,因为编译器需要知道它的大小,以便知道如何分配一个
Bar。 -
为什么?尚未创建类 Bar 的实例。那么为什么它需要标签 3 中的尺寸呢?请记住,尚未在该行创建类 Bar 的对象。类 Bar 的对象仅在类 Bar 定义之外创建,如标记 5 所示
-
与头文件中声明的全局变量完全相同的原因。静态类成员,如全局变量,最终需要在编译单元(.cpp 文件)中定义一个可以链接到的地址。
-
@yapkm01
Bar mem3;只是写Bar mem3 = Bar();的简写。您可以通过查看here 来查看。 (Bar类的默认构造函数被调用,但在您的情况下,由于尚未定义Bar,因此会弹出错误。) -
该语言只要求明确定义类型的大小。如果一个类型包含它自己的一个实例,它的大小是无限的,并且编译器阻止你这样做,甚至在该类型的对象被创建之前。我可以问为什么这是一个问题吗?你有什么特别的理由想要编译器接受的类型吗?