繁体   English   中英

为什么嵌套类不能有一个成员,其类型是封闭类之一?

[英]Why a nested class can't have a member the type of which is the one of the enclosing class?

一个的类的方法C需要返回一个struct包含一对整数和一个新鲜实例C 它可能看起来很尴尬,但考虑到整体设计,这很有意义(想想一个Waveform类将一系列自身作为副本返回,并指示范围的开始和结束位置)。

问题是似乎不允许这样做。 我可以重新设计我的类以避免这个问题,但是你可以解释一下为什么从编译器的角度来看,这不可能做到

struct S {
    struct S2 {
        S s;
    };
};

因为S是一个不完整的类型(这是编译器错误),相反,这是完全正常的

struct C {
    struct C1 {
        C makeC() { return C(); }
    };
};

哪里有实质性的区别?

在您尝试定义S::S2 ,类型S仍然是不完整类型 ,因为其定义尚未完成。 类数据成员必须具有完整类型。

您可以像这样轻松修复它:

struct S
{
    struct S2;   // declare only, don't define

    // ...
};

struct S::S2
{
    S s;         // now "S" is a complete type
};

C ++的设计决定本质上是在完成定义之前不考虑类型完成。 这可以防止许多病理情况,例如以下示例:

struct X
{
    struct Y { X a; };

    int b[sizeof(Y)];      // "sizeof" requires a complete type
};

如果要定义类,则需要完整定义所有嵌入(非引用和非指针)成员。 在定义类时,类没有完全定义。 也就是说,在类定义中,定义的类仅仅是声明的,而不是定义的。

也就是说,您仍然可以在嵌套类中拥有类的成员。 您只需在定义外部类后定义嵌套类:

struct S {
    struct S2;
};

struct S::S2 {
    S s;
};

由于S完全由第一个闭合支撑定义,因此在此之后它可以用作嵌入式构件。

在类定义中定义成员函数时,定义将被解析,就好像它出现在最接近的命名空间级别上的类定义之后。 也就是说,成员函数定义知道完全定义的类。 这同样适用于嵌套类。

我不确切知道为什么,但我可以推测这个反例:

struct S {
    struct S2 {
        S s;
    };
    S2 s2;
};

在这种情况下,在扫描S2之前扫描S并确定其大小的尝试将失败。 我怀疑递归可能会给编译器带来困难,而这些困难往往是标准中规则的原因。

也就是说,我认为您的解决方案不适合您所描述的问题。 我会在S上制作S2模板,而不是嵌套。 然后我将能够使用引用S&作为模板参数,而不是S本身。 因此,范围将由两个整数和对原始数组对象的引用表示。 从这个范围制作一个新的副本将是一个单独的操作。

编译器无法计算所包含类的大小。

你可以写S* s; 虽然。

这个答案着重于两个例子之间的区别 ,因为其他答案已经解释了为什么第一个例子不起作用。

简而言之,您的第一个示例在S中使用S ,要求S完成。

您的第二个示例要求在编译函数体后立即完成C 你的代码相当于

struct C {
    struct C1 {
        C makeC();
    };
};

inline C C::C1::makeC() {
    return C();
}

这意味着,编译器会自动“推迟”函数体。 对于函数声明 ,编译器只需要知道C是一个类型,但如果C不完整,那么它就可以工作,这就是那个点。 在编译函数定义时 ,类型C现在已完成。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM