Класс смешивания и структура
Я хорошо знаю разницу между классом и структурой, однако я борюсь за авторитетное утверждение, если это хорошо определено:
// declare foo (struct)
struct foo;
// define foo (class)
class foo {
};
// instance of foo, claiming to be a struct again! Well defined?
struct foo bar;
// mixing class and struct like this upsets at least one compiler (names are mangled differently)
const foo& test() {
return bar;
}
int main() {
test();
return 0;
}
Если это поведение undefined, кто-то может указать мне в сторону авторитетной (например, главы и стиха из ISO) ссылки?
Компилятор с проблемами с этим (Carbide 2.7) относительно старый, и все другие компиляторы, с которыми я его пробовал, совершенно счастливы с этим, но ясно, что ничего не доказывает.
Моей интуицией было это поведение undefined, но я не могу найти ничего, чтобы подтвердить это, и я удивлен, что ни одна из версий GCC или Comeau, чтобы предупредить об этом.
Ответы
Ответ 1
Мне кажется, что это определенное поведение. В частности, в § 9.1/2 говорится:
Декларация, состоящая только из class-key identifier ;
, является либо реконструированием имя в текущей области действия или декларацию прямого имени идентификатора в качестве имени класса. Он вводит имя класса в текущую область.
Стандарт различает использование class
, struct
или union
при определении класса, но здесь, говоря об объявлении, такого различия не делается - использование одного class-key
эквивалентно любому другому.
Ответ 2
Из Предупреждение C4099: имя типа, впервые увиденное с использованием "класса" , которое теперь видно с помощью "struct" (MS VS 2k8), кажется, что по крайней мере некоторые компиляторы калечат по-разному в зависимости по ключевому слову, поэтому лучше не полагаться на него, даже если это технически разрешено (я не могу найти подтверждающую ссылку).
Ответ 3
Технически код в порядке, в соответствии со стандартом языка. Однако, поскольку по крайней мере один из самых популярных компиляторов выдает предупреждение для этого, он не работает на практике.
"В теории нет разницы между теорией и практикой. В принципе, есть".
Ответ 4
В С++ структура - это класс. В частности:
Структура - это класс, определенный с помощью ключ класса struct
. (ISO/IEC FDIS 14882: 1998 (E) 9-4)
Это означает, что ваш класс, который не был определен с помощью struct
, определенно не является структурой. Следовательно, ваше объявление forward с ключом struct class является ошибочным. Я не знаю какой-либо части спецификации, которая позволяет прямому объявлению использовать ключ класса, который явно ошибочен. Я уверен, что рассматриваемые компиляторы с ленивым отношением одинаково относятся к структурам и классам и замалчивают неправильное объявление. Ошибка может не потребоваться от компилятора в этом сценарии, но также и не должна быть неожиданной.
Ответ 5
Я не знаю, соответствует ли это undefined (или любой другой категории не строгого соответствия) по стандарту C, но я знаю, что если у вас есть две единицы перевода, которые не согласны о том, объявлен ли тип "foo" как "класс" или "структура", например:
TU 1
struct foo;
void f(foo&) { ... }
TU 2
class foo { ... };
void f(foo&);
void g()
{
foo x;
f(x);
}
то, по крайней мере, некоторые компиляторы (в частности, MSVС++) будут кастовать имя f
по-разному в каждой единицы перевода, поэтому определение f
в TU 1 не удовлетворяет ссылке на f
в TU 2 и вы получаете ошибку ссылки. Это происходит в реальной жизни, когда у вас есть заголовок A.h
, который определяет класс A
, и ему нужно ссылаться на классы B
, C
и D
, но достаточно их прямого объявления (так что это довольно разумно, не включает B.h
и т.д.) - вам лучше использовать одно и то же ключевое слово для тех передовых объявлений, которые имеют фактические определения!
Ответ 6
MSVC10 выдает предупреждение, а на странице предупреждения указывается тип, указанный в определении.
http://msdn.microsoft.com/en-us/library/695x5bes.aspx