объявление класса с ключевым словом struct и наоборот

Но, конечно, нам не стоит даже думать о таких вещах, я знаю, но все же это довольно интересно:

class A; //declaration
struct A {...}; //definition

struct B; //declaration
class B {...}; //definition

Когда я думаю об этом, я не вижу никаких проблем, если бы такое действительно было разрешено (потому что структура и класс по сути одно и то же). Но так ли это (стандартно)?

MSVC принимает и компилирует его с предупреждением.


person Armen Tsirunyan    schedule 26.06.2011    source источник


Ответы (2)


Это разрешено стандартом, но, как предупреждают некоторые компиляторы, не очень полезно.

Я считаю, что предупреждение вызвано/было вызвано тем, что MSVC использует другое искажение имен для структур и классов, что сделало бы его еще менее полезным...


По запросу от @Armen:

7.1.5.3 Подробные спецификаторы типов, p3

... в любом уточненном спецификаторе типа ключевое слово enum должно использоваться для ссылки на перечисление (7.2), union ключ класса должен использоваться для ссылки в объединение (пункт 9), а class или struct ключ класса должен использоваться для ссылки на класс (пункт 9), объявленный с использованием class или struct ключ класса< /эм>.

person Bo Persson    schedule 26.06.2011
comment
Любые цитаты из стандарта, которые позволяют это? - person Armen Tsirunyan; 29.06.2011
comment
@Armen - Добавлена ​​цитата, хорошо спрятанная в главе 7. :-) - person Bo Persson; 29.06.2011

Согласно C++03 Standard 9.1 – 2

"Определение класса вводит имя класса в область, в которой оно определено, и скрывает любой класс, объект, функцию или другое объявление этого имени в охватывающей области (3.3)".

Так что это действительно в соответствии со стандартом.

Немного поиграем с примером кода:

#include<iostream>

class A; //declaration 
struct A { int i;}; //definition  
struct B; //declaration 
class B {int j;}; //definition 

int main()
{
    A obj;
    obj.i = 10;
    B obj2;
    obj2.j = 10;
    std::cout<<"sizeof"<<sizeof(struct B);
    return 0;
}

Вот результат:

prog.cpp: In function ‘int main()’:
prog.cpp:6: error: ‘int B::j’ is private
prog.cpp:13: error: within this context

Единственная разница между структурой и классом С++ заключается в том, что спецификатор доступа по умолчанию для структуры является общедоступным, а для класса — закрытым.

Итак, из приведенного выше примера:
В этом случае компилятор обрабатывает A как structure и
B как class

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

person Alok Save    schedule 26.06.2011
comment
@Als: Как этот абзац означает, что то, что я написал, разрешено? оо - person Armen Tsirunyan; 26.06.2011
comment
@Армен Цирунян: Если определение скрывает какое-либо объявление этого имени в охватывающей области, то разве то, что вы написали, не должно быть разрешено в соответствии со стандартной цитатой? - person Alok Save; 26.06.2011
comment
@Als: я думаю, что и struct A, и class A {...} относятся к одному и тому же объекту, имя не скрывается ... Или я что-то упустил? - person Armen Tsirunyan; 26.06.2011
comment
@Армен Цирунян: Я оцениваю цитату, Наличие определения struct A {...}; скрывает объявление class A;. - person Alok Save; 26.06.2011
comment
@Als: Но скрыть имя недостаточно, не так ли? Компилятор должен понимать, что определение класса ссылается на предыдущее объявление... Я не прав? - person Armen Tsirunyan; 28.06.2011
comment
@Армен Цирунян: Обновил ответ. - person Alok Save; 29.06.2011
comment
Здесь ничего не спрятано... полностью определите class A и struct A в приведенном выше коде и посмотрите, что произойдет. - person Dennis Zickefoose; 29.06.2011
comment
@Als: Это не единственная разница. Не забывайте о наследовании. - person Lightness Races in Orbit; 29.06.2011