Можно ли назвать член класса тем же именем, что и его тип (другой класс)?

Попытка скомпилировать следующий код на разных компиляторах дает мне два разных результата:

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

Как видите, внутри T, У меня есть объект, названный так же, как ранее определенный класс S,


На GCC 4.7.2, Я получаю следующую ошибку относящийся к S S; декларация внутри T:

ошибка: объявление ‘S T :: S’ [-fpermissive] ошибка: меняет значение ‘S’ с ‘struct S’ [-fpermissive]

Тем не менее, перемещая его за пределы класса (или в main) работает отлично:

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

Что именно означает ошибка, которую она мне дает?


В Visual Studio 2012 все это компилируется и запускается без ошибок. Вставить его в этот компилятор Clang 3.0 также не дает мне ошибок.

Какой правильный? Могу ли я на самом деле сделать это или нет?

9

Решение

gcc правильный, из [3.3.7 Область действия класса]

Имя N, используемое в классе S, должно ссылаться на то же объявление в его
контекст и при переоценке в завершенном объеме 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;
};
14

Другие решения

Этот код неверен, диагностика не требуется. Как гласит диагностика, если в объявлении используется имя, а имя имеет другое значение, чем при взгляде в конце определения класса, программа не сформирована, диагностика не требуется.

6

@JesseGood предоставит полный ответ, но если вы действительно хотите сделать это без ошибок, вы можете использовать полное имя типа, и оно будет работать следующим образом:

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

Нет, ошибки нет, так как S в вашем классе T::S и его тип ::S!

6
По вопросам рекламы [email protected]