12

尝试在不同的编译器上编译以下代码会给我两个不同的结果:

struct S{};
struct T{S S;};
int main(){}

如您所见,在内部T,我有一个与之前定义的类同名的对象S


在 GCC 4.7.2 上,我收到以下S S;与内部声明有关的错误T

错误:'ST::S' [-fpermissive] 的声明
错误:从'struct S' [-fpermissive] 更改'S' 的含义

但是,将其移出类(或移入main可以正常工作

struct S{};
S S;
int main(){}

它给我的错误到底是什么意思?


在 Visual Studio 2012 中,整个程序编译并运行,没有任何错误。将它粘贴到这个 Clang 3.0 编译器中也不会给我任何错误。

哪个是对的?我真的可以这样做吗?

4

3 回答 3

16

gcc 是正确的,来自 [3.3.7 Class Scope]

在 S 类中使用的名称 N 应在其上下文中引用相同的声明,并且在 S 的完整范围内重新评估时。违反此规则不需要诊断。

但是,请注意no diagnostic is required,因此所有编译器都符合要求。

原因在于类范围的工作方式。当你写的时候在整个S S; S中是可见的,并且在你使用时改变了含义。S

struct S{};
struct T{
    void foo()
    { 
        S myS; // Not possible anymore because S refers to local S
    }
    S S;
};
于 2012-10-17T21:34:58.690 回答
8

@JesseGood 提供了一个完整的答案,但如果你真的想这样做没有任何错误,你可以使用类型的全名,它的工作方式如下:

struct S {};
struct T { ::S S; };
int main() {return 0;}

不,没有错误,因为S在您的课程中是T::S并且它的类型是::S

于 2012-10-17T22:38:19.333 回答
6

此代码格式错误,无需诊断。就像诊断所说的那样,如果声明使用了一个名称,并且该名称的含义与在类定义末尾查找时的含义不同,则程序是错误的,不需要诊断。

于 2012-10-17T21:34:44.167 回答