C++中的嵌套子类

gil*_*mec 12 c++ subclass inner-classes

我正在尝试创建一个嵌套类,它也是其父类的子类:

struct X { struct Y : public X {}; };
Run Code Online (Sandbox Code Playgroud)

不幸的是,在C++中似乎不允许这样做,因为g ++会产生错误

错误:无效使用不完整类型'struct X'

但是,我的实际代码有X一个模板类:

template<typename T> struct X
{ struct Y : public X {}; };
Run Code Online (Sandbox Code Playgroud)

我收到相同的消息,但这次只是一个警告:

警告:无效使用不完整类型'struct X <T>'

我的问题是:为什么前一种情况是非法的,而模板化的案例只是发出警告?模板化版本的工作方式完全符合我的预期(我可以创建实例X<T>::Y,将它们转换为X<T>等等),但警告是否意味着我不应该使用它?如果忽略警告,我可能会遇到什么问题?

Yam*_*vic 9

回答基本问题:你得到一个警告,因为模板还没有实例化,所以它不会打扰任何人.

在这两种情况下,解决这个问题的方法是定义已经知道布局X::Y的点X,从而Y可以正确地推导出布局.你可以这样做:

struct X { struct Y; }
struct X::Y {};
Run Code Online (Sandbox Code Playgroud)


eer*_*ika 2

从技术上讲,就编译器而言,在实例化Xtemplate () 之前不需要知道base () 的布局。X并且模板( X) 在完全定义之前可能不会被实例化。此时,它的布局就已知了。

从模板中获取错误的最简单方法是尝试Y在内部进行 istantiate X

template<typename T> struct X {
    struct Y : public X {};
    Y y;
};
Run Code Online (Sandbox Code Playgroud)

在编译器的早期版本中,在您显示的情况下没有警告,但它是在某个时候添加的。以下是GCC bugtracker中有关该警告是否虚假的讨论。标准是否允许存在一些不确定性,但他们的结论是不允许的。

因此,这两种情况都是标准不允许的,但 GCC 继续与后者合作,因为它可以。

Yam Marcovic 展示了如何X::Y以符合标准的方式进行定义。gcc bugtracker 中显示了类似的相同示例。