C++ 语法“A::B:A ;”是啥意思?意思是
Posted
技术标签:
【中文标题】C++ 语法“A::B:A ;”是啥意思?意思是【英文标题】:What does C++ syntax “A::B:A ;” meanC++ 语法“A::B:A ;”是什么意思?意思是 【发布时间】:2018-05-12 19:09:09 【问题描述】: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;
【问题讨论】:
不需要首字母struct B;
。它不在代码中的任何地方使用。
@AnT 只是在这个翻译单元中没有使用它。但就这个例子而言,我认为没有其他翻译单元,并且很有可能操作可能有认为这是必须的。
@sjsam:即使B
在另一个翻译单元中使用,在这个TU中声明仍然是多余的。
命名空间 A 中的内部 B 作为 A 的子节点
【参考方案1】:
这个定义
struct A
struct B;
;
使用嵌套结构 B
1 的声明定义结构 A
。 B
的完全限定名称是 A::B
,您可以说 B
在 A
的“命名空间”内。那么这个:
struct A::B : A // Note I added spaces
;
是A::B
的定义,单个:
指定它派生自A
。
现在,有趣的部分是A::B::A::B
。让我们剖析一下:
A::B
命名嵌套结构。
A::B::A
访问B
内注入的类名A
。注入是由于继承。
A::B::A::B
在 A
中再次命名嵌套结构 B
。
您可以无限继续,或者至少直到您的编译器达到其翻译限制2。
一个有趣的智力练习,但避免像实际代码中的瘟疫一样。
[class.qual]/1 解释了查找的工作原理
如果 qualified-id 的 nested-name-specifier 指定了一个类,则 在 nested-name-specifier 之后指定的名称在 类的范围([class.member.lookup]),除了情况 下面列出。该名称应代表该组织的一个或多个成员 类或其基类之一(子句 [class.derived])。
上面的文字允许我们命名基类,因为[class]/2
class-name 也被插入到类本身的作用域中; 这被称为 injected-class-name。出于访问目的 检查,injected-class-name 被视为公共的 会员名。
上面清楚地表明,以A::
开头的完全限定名称允许您指定成员或基类。由于A
没有基数,您只能指定A::B
(“成员类型”)。但是A::B
也提名了一个班级。所以我们可以用A::B::
指定that 的基数或成员,这样我们就可以命名A::B::A
。现在冲洗并重复。
1 - 注意它完全是另一个B
。与全局 struct B
完全无关。2 - 根据 [implimits]/2.36 建议的最小值为 256
【讨论】:
如果替换 std::cout 会发生什么 @devsh - 你并没有真正进行递归。您只需回溯并选择两种类型中的一种。无论您重复多少次,该表达式中只有两种类型。所以sizeof( A::B::A::B::A::B::A::B::A::B)
与sizeof(A::B)
没有什么不同
@devsh - 等等。我将添加一个标准报价。我们会看看它是否会为您解决问题。
@devsh - 在那里。这就是报价。请注意它是如何表示如果“前缀”命名一个类。 如何 类被命名并不重要。我们命名它,我们可以再次使用::
来访问其中的某些内容。
对新编码员的注意A::B::A::B::A::B
可能会让你陷入困境,或者充其量是被画成四等分。命名很难,但并不难:-)【参考方案2】:
首先struct B;
是结构B
在全局命名空间中的前向声明。这可能会令人困惑,因为它实际上与此示例无关。这个全局B
可以作为::B
或B
访问。
struct A
struct B;
;
是在全局命名空间中定义 struct A
,并带有 nested struct B
的前向声明(与之前在全局命名空间中声明的 B
不同)。这个嵌套的B
可以通过::A::B
或A::B
访问。
struct A::B:A
;
是从A
继承的结构A
的嵌套结构B
的定义(省略了访问说明符)。可以改写为:
struct A::B
: public A
;
请注意,像这样在 A
定义中编写嵌套结构 B
的定义是行不通的:
struct A
struct B: A // error: A is incomplete at this point
;
;
最后A::B::A
指的是嵌套结构B
的基类,即A
,所以A::B::A::B
就相当于A::B
。
【讨论】:
澄清一下(我自己和其他想知道的人)——struct
的默认继承访问修饰符是public
,而不是class
的private
? (因此说: public A
是等价的)
@QPaysTaxes 是的,struct
的默认访问修饰符是 public
,它适用于字段、方法、嵌套类型和基类。请注意,这有助于保持与 C 的向后兼容性,否则 C 结构的所有字段都将无法访问。
@devsh A::B::A::B::A::B::A::B::A::B
不是递归继承。它只是一个嵌套类型访问链,仍然等同于A::B
。另请注意,递归继承在 C++ 中是不可能的,因为在某些时候,继承链中的一种类型会不完整。并且给定的代码不包含递归继承。
@devsh 也可以让这个链在没有任何继承的情况下工作:struct B; struct A using B = ::B; ; struct Busing A = ::A; ;
@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
。以上是关于C++ 语法“A::B:A ;”是啥意思?意思是的主要内容,如果未能解决你的问题,请参考以下文章