这是众所周知的,一个不能有一个会员你定义的类型:
class Foo {
Foo member;
};
Run Code Online (Sandbox Code Playgroud)
原因是这是一个无限递归,无限大的对象.但是,我们可以拥有静态成员:
class Foo {
static Foo member;
};
Run Code Online (Sandbox Code Playgroud)
我们可以这样做,因为Foo
它就像一个命名空间; Foo
不包含的实例.member
,所以没有无限的引用.换句话说,.member
属于类,而不属于实例.我想做的非常相似:
class Foo {
class Bar {
Foo member;
};
};
Run Code Online (Sandbox Code Playgroud)
再次,Foo
就像命名空间一样.实例Foo
实际上是空的.我必须创建一个非静态字段Bar Foo::bar;
来开始获取布局问题.不幸的是,我的编译器不同意(例如GCC):
<source>:3:14: error: field 'member' has incomplete type 'Foo'
Foo member;
^~~~~~
Run Code Online (Sandbox Code Playgroud)
出于什么技术原因这是不允许的?
das*_*ght 21
长话短说,禁止这个比允许更容易.
下面是一个示例,它显示了可能有什么困难:C++允许您将嵌套类定义与成员声明相结合,如下所示:
class Foo {
class Bar {
Foo member;
} bar; // <<== Here
};
Run Code Online (Sandbox Code Playgroud)
很明显为什么必须禁止这个定义:与可能没有的类定义不同,成员定义使得大小计算变得不可能.
当然,标准的编写者可以允许类定义通过,但代价是给编译器编写者额外的工作.但是,看起来他们认为允许这个功能并不值得这么麻烦,所以他们没有把它作为一个例外,要求在声明一个实例时完成类的完成.
Owe*_*hoy 19
你做什么没有什么不对,你可以用不同的语法来做.
由于编译器想要确定类Bar的大小,它需要知道类Foo的大小,但是Foo的定义还没有完成(源代码还没有被编译器完全解析).Foo的定义必须在Bar中使用之前完成.
而是尝试在Foo中声明Bar,然后在Foo之后完成Bar的定义,这样可以确定Foo的大小以便在Bar中使用.
class Foo {
class Bar;
};
class Foo::Bar {
Foo member;
};
Run Code Online (Sandbox Code Playgroud)
这是不允许的,因为您无法使用具有不完整类型的句点定义类.在类定义的最后,类变得完整,只有在知道其所有成员的大小时才可以.
例如,出于同样的原因,您得到相同的错误,没有嵌套这样的类:
class Foo;
class Bar {
Foo member;
};
Run Code Online (Sandbox Code Playgroud)
当然,在您的示例中,语言可以推迟完成Foo::Bar
直到Foo
定义的定义,但这与通常定义类的方式不一致.Foo::Bar
在完全定义之后,您会在源代码中的某个点处出现不完整的奇怪行为.