下面的第一个代码片段编译,但第二个没有。 为什么?
下面的代码片段编译( 演示 ):
struct A{ int i = 10; }; int main() { struct A{ int i = 20; }; struct A; struct A a; }
但是这不是:
struct A{ int i = 10; }; int main() { // struct A{ int i = 20; }; struct A; struct A a; }
我可以看到,答案可能是由标准中的这些段落给出的:
[basic.lookup.elab] / 2和[basic.scope.pdecl] / 7 。
但是我真的不知道如何从这两段推导出上面所示的不同行为。
请注意,在第一个示例中, struct A
不是首先在阐述types说明符 struct A;
,但在main()
的struct A
的定义中。
在第二个例子中, struct A
也没有在elaborated-type-specifier struct A;
首先声明struct A;
,而是在全局范围的struct A
的定义中。
每个例子都包含两个不同类的声明,都是名字A
让我们通过将其中的一个重命名为B
来区分这些类:
struct A{ int i = 10; }; int main() { struct B{ int i = 20; }; struct B; struct B b; }
以上在语义上与第一个例子相同。 A
类从不使用。
struct A{ int i = 10; }; int main() { struct B; struct B b; }
这在语义上与第二个例子相同。 您正试图创build一个不完整types的对象,即前向声明的类B
将B
重命名为A
并不会改变任何内容,因为在main
中声明A
会影响全局范围内其他A
的声明。
[basic.lookup.elab] / 2
如果精化types说明符没有嵌套名称说明符 ,并且精确types说明符出现在具有以下forms的声明中:
class-key
attribute-specifier-seq
optidentifier
;
详细types说明符是一个声明,它引入了在[basic.scope.pdecl]中描述的类名称 。
所以struct A;
是在声明范围内引入类名的声明。 在任何情况下都不可以引用在外部范围内声明的类。
[basic.scope.pdecl] / 7
[ 注意:其他forms的详细说明types说明符不会声明新的名称 – 结束说明 ]
通过暗示,这种forms化的types说明符声明了一个新的名字。
在第二个例子中, struct A;
是主函数范围内的一个名为A的结构的前向声明。 这个结构将比全局struct A
更struct A
。 下一行定义了一个叫做struct A
的variables。 由于struct A
是在main函数的作用域中声明的,所以编译器会在那里search它的定义。 它没有find一个(它被注释掉)。 第一个例子编译是因为在同一个范围内有定义。 下面的例子会进行编译,因为它指定了A
在全局名称空间中:
struct A{ int i = 10; }; int main() { // struct A{ int i = 20; }; struct A; struct ::A a; }
它不能编译,因为它找不到A的定义。
int main() { // struct A{ int i = 20; }; struct A; struct A a; }
上面的代码等同于你的第一个例子,因为全局A被本地A映射。在第二个例子中,A没有定义。 这只是一个原型。 原型应该放在需要定义的代码片段之前,当定义被放置在需要的代码之后。 如果编译器找不到该定义,它将会失败,因为它不知道A应该是什么(全局定义被本地原型所遮蔽,导致它被忽略)。