C++语法"A :: B:A {};"是什么意思

dev*_*vsh 64 c++ syntax struct scope-resolution

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;
}
Run Code Online (Sandbox Code Playgroud)

Sto*_*ica 119

这个定义

struct A {
    struct B;
};
Run Code Online (Sandbox Code Playgroud)

A使用嵌套struct B1的声明定义结构.完全限定名称BA::B,你可以说B是在"命名空间"里面A.然后这个:

struct A::B : A { // Note I added spaces
};
Run Code Online (Sandbox Code Playgroud)

是定义A::B,单个:指定它是从哪个派生而来的A.

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

  1. A::B 命名嵌套结构.
  2. A::B::A访问A里面注入的类名B.注入是由于继承.
  3. A::B::A::B名嵌套结构BA一次.

并且您可以继续ad-infinitum,或者至少在您的编译器满足其转换限制2之前.

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


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

如果嵌套名称说明符一的合格-ID提名一个类,则后指定的名称嵌套名称说明符在类([class.member.lookup])的范围抬头,除了例列出下面.该名称应代表该类或其基类之一的一个或多个成员(Clause [class.derived]).

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

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

以上清楚地说明,启动完全限定名称A::允许您指定成员或基类.由于A没有基础,您只能指定A::B("成员类型").但A::B也提名了一个班级.因此,我们可以指定一个基地或成员认为也有A::B::,这让我们的名字A::B::A.现在冲洗并重复.


1 - 注意它完全是另一个B.与全球无关struct B.
2 - 根据[implimits] /2.36建议的最小值256

  • 新编码器的注意事项`A :: B :: A :: B :: A :: B`可能会让你挂起或最多被绘制和四分之一.命名事情很难,但这并不难:-) (8认同)
  • @devsh - 你真的没有做递归.您只需回溯并选择两种类型中的一种.在该表达式中只有两种类型,无论重复多少次.所以`sizeof(A :: B :: A :: B :: A :: B :: A :: B :: A :: B)`与`sizeof(A :: B)没什么区别` (3认同)

use*_*670 21

首先struct B;B全局命名空间中struct的前向声明.它可能令人困惑,因为它在这个例子中实际上并不相关.这个全局B可以作为::B或仅仅访问B.

struct A {
    struct B;
};
Run Code Online (Sandbox Code Playgroud)

A全局命名空间中struct的定义,带有嵌套 struct 的前向声明B(与先前B在全局命名空间中声明的不同).这个嵌套B可以作为::A::B或访问A::B.

struct A::B:A {
};
Run Code Online (Sandbox Code Playgroud)

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

struct A::B
:   public A
{
};
Run Code Online (Sandbox Code Playgroud)

请注意,B在这样的A定义中编写嵌套struct 的定义是行不通的:

struct A {
    struct B: A { // error: A is incomplete at this point
    };
};
Run Code Online (Sandbox Code Playgroud)

最后A::B::A是指嵌套struct的基类B,也就是说A,A::B::A::B等同于A::B.

  • @devsh因为`A :: B :: A`等同于'A`.您可以通过编写`static_assert(:: std :: is_same_v <A,A :: B :: A>);`来验证这一点.所以这个链可以从左到右简化,就像`A :: B :: A :: B :: A :: B :: A :: B`然后`A :: B :: A :: B :: A :: B`然后`A :: B :: A :: B`然后是'A :: B`. (2认同)