66

C++ 语法struct A::B:A {};是什么意思?C++ 标准中描述的名称定义(或访问)在哪里?

#include <iostream>

struct B;

struct A {
    struct B;
};

struct A::B:A {
};

int main() {
    A::B::A::B b;
    std::cout<<"Sizeof A::B::A::B is " << sizeof(A::B::A::B)<<std::endl;
    return 0;
}
4

2 回答 2

122

这个定义

struct A {
    struct B;
};

定义一个A带有嵌套结构B1声明的结构。的完全限定名称BA::B,您可以说B是在 的“命名空间”内A。然后这个:

struct A::B : A { // Note I added spaces
};

是 的定义A::B,单号:指定它是从派生A

现在,有趣的部分是A::B::A::B。让我们剖析一下:

  1. A::B命名嵌套结构。
  2. A::B::AA访问内部注入的类名B。注入是由于继承。
  3. A::B::A::B再次命名嵌套结构BA

而且您可以无限继续,或者至少直到您的编译器满足其翻译限制2

一个有趣的智力练习,但避免像实际代码中的瘟疫一样。


[class.qual]/1解释了查找的工作原理

如果限定 ID的嵌套名称说明符指定了一个类,则在该嵌套名称说明符之后指定的名称([class.member.lookup])在类的范围内查找,但列出的情况除外以下。该名称应代表该类或其基类之一的一个或多个成员(子句 [class.derived])。

上面的文字允许我们命名基类,因为[class]/2

也被插入到类本身的范围内;这被称为注入类名。出于访问检查的目的,注入的类名被视为公共成员名。

上面清楚地表明,以完全限定名称开头A::允许您指定成员或基类。由于A没有基础,您只能指定A::B(“成员类型”)。还要A::B提名一个班级。所以我们也可以用 指定它的基数或成员这样A::B::我们就可以命名A::B::A。现在冲洗并重复。


1 - 请注意,它完全是 other B。与全局无关struct B
2 - 根据[implimits]/2.36建议的最小值为 256

于 2017-11-29T06:48:27.293 回答
21

首先是全局命名空间struct B;中结构的前向声明。B这可能会令人困惑,因为它实际上与此示例无关。这个全局变量B可以以.::B或 . 的形式访问B

struct A {
    struct B;
};

是全局命名空间中结构的定义,具有嵌套结构A的前向声明(与先前在全局命名空间中声明的不同)。这个嵌套可以作为或访问。BBB::A::BA::B

struct A::B:A {
};

是继承自B的结构的嵌套结构的定义(省略访问说明符)。它可以重写为:AA

struct A::B
:   public A
{
};

请注意,像这样在定义中编写嵌套结构BA定义是行不通的:

struct A {
    struct B: A { // error: A is incomplete at this point
    };
};

而finallyA::B::A是指嵌套struct的基类B,也就是to A,soA::B::A::B等价于just A::B

于 2017-11-29T07:00:08.983 回答