为什么内部*定义*不能使用他们的父类?

ima*_*ett 14 c++

这是众所周知的,一个不能有一个会员你定义的类型:

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)

很明显为什么必须禁止这个定义:与可能没有的类定义不同,成员定义使得大小计算变得不可能.

当然,标准的编写者可以允许类定义通过,但代价是给编译器编写者额外的工作.但是,看起来他们认为允许这个功能并不值得这么麻烦,所以他们没有把它作为一个例外,要求在声明一个实例时完成类的完成.

  • 偏离主题:感谢(和一些赞成)关于那个空行印刷品的非常有用的评论! (2认同)

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)

  • OP问:"这是不允许的技术原因?" 我明确表示它与确定一个班级的大小有关.由于Foo的定义不完整,因此无法确定Foo的大小,因此无法在Bar中使用. (8认同)

Ros*_*dge 6

这是不允许的,因为您无法使用具有不完整类型的句点定义类.在类定义的最后,类变得完整,只有在知道其所有成员的大小时才可以.

例如,出于同样的原因,您得到相同的错误,没有嵌套这样的类:

class Foo;
class Bar {
    Foo member;
};
Run Code Online (Sandbox Code Playgroud)

当然,在您的示例中,语言可以推迟完成Foo::Bar直到Foo定义的定义,但这与通常定义类的方式不一致.Foo::Bar在完全定义之后,您会在源代码中的某个点处出现不完整的奇怪行为.