Подтвердить что ты не робот

Класс смешивания и структура

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

// 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, чтобы предупредить об этом.

4b9b3361

Ответ 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 и т.д.) - вам лучше использовать одно и то же ключевое слово для тех передовых объявлений, которые имеют фактические определения!