下面的第一个代码片段编译,但第二个没有。 为什么?

下面的代码片段编译( 演示 ):

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 opt identifier ;

详细types说明符是一个声明,它引入了在[basic.scope.pdecl]中描述的类名称

所以struct A; 是在声明范围内引入类名的声明。 在任何情况下都不可以引用在外部范围内声明的类。

[basic.scope.pdecl] / 7

[ 注意:其他forms的详细说明types说明符不会声明新的名称 – 结束说明 ]

通过暗示,这种forms化的types说明符声明了一个新的名字。

在第二个例子中, struct A; 是主函数范围内的一个名为A的结构的前向声明。 这个结构将比全局struct Astruct 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应该是什么(全局定义被本地原型所遮蔽,导致它被忽略)。

Interesting Posts