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

时间:2016-12-17 11:26:52

标签: c++

您定义类型的well-known that one cannot have 成员

class Foo {
    Foo member;
};

原因是这是一个无限递归,无限大的对象。但是,我们可以拥有静态成员:

class Foo {
    static Foo member;
};

我们可以这样做,因为Foo就像命名空间一样; Foo的实例不包含.member,因此没有无限引用。换句话说,.member属于类,而不属于实例。我想做的非常相似:

class Foo {
    class Bar {
        Foo member;
    };
};

再一次,Foo就像命名空间一样。 Foo的实例实际上是空的。我必须创建一个非静态字段Bar Foo::bar;来开始获取布局问题。不幸的是,我的编译器不同意(e.g. GCC):

<source>:3:14: error: field 'member' has incomplete type 'Foo'
Foo member;
^~~~~~

出于什么技术原因这是不允许的?

3 个答案:

答案 0 :(得分:21)

长话短说,不允许这样做比允许更容易。

这是一个显示可能困难的例子:C ++允许您将嵌套类定义与成员声明相结合,如下所示:

class Foo {
    class Bar {
        Foo member;
    } bar; // <<== Here
};

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

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

答案 1 :(得分:19)

你做什么没有什么不对,你可以用不同的语法来做。

由于编译器想要确定类Bar的大小,它需要知道类Foo的大小,但是Foo的定义还没有完成(源代码还没有被编译器完全解析)。 Foo的定义必须在Bar中使用之前完成。

相反尝试在Foo中声明Bar,然后在Foo之后完成Bar的定义,这样可以确定Foo的大小以便在Bar中使用。

class Foo {
    class Bar;
};
class Foo::Bar {
  Foo member;
};

答案 2 :(得分:6)

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

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

class Foo;
class Bar {
    Foo member;
};

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