Смешивание класса и структуры - PullRequest
17 голосов
/ 01 февраля 2011

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

// 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;
}

Если это неопределенное поведениеМожет ли кто-нибудь указать мне направление авторитетного (т. е. главы и стиха из ИСО) ссылки?

Компилятор с проблемами при работе с ним ( Carbide 2.7 ) является относительно старым, и все остальные компиляторы, на которых я его пробовал, совершенно довольны этим, но ясно, что это ничего не доказывает.

Моя интуиция заключалась в том, что это должно быть неопределенным поведением, но я не могу найти ничего, чтобы это подтвердить, и я удивлен, что ни одна из версий GCC или Comeau так сильно не предупреждены оэто.

Ответы [ 6 ]

11 голосов
/ 01 февраля 2011

Мне кажется, это определенное поведение.В частности, §9.1 / 2 гласит:

Объявление, состоящее исключительно из class-key identifier ;, представляет собой либо повторное объявление имени в текущей области видимости, либо предварительное объявление идентификатора в качестве имени класса.Он вводит имя класса в текущую область.

Стандарт различает использование class, struct или union, когда определяет класс, но здесь речь идетв отношении декларации такое различие не проводится - использование одного class-key эквивалентно любому другому.

5 голосов
/ 03 февраля 2011

Технически код в порядке, в соответствии со стандартом языка. Однако, по крайней мере, один из самых популярных компиляторов выдает предупреждение за это, на практике это не работает.

"Теоретически нет разницы между теорией и практикой. На практике есть."

4 голосов
/ 01 февраля 2011

С Предупреждение C4099: имя типа, впервые увиденное с использованием 'class', теперь видно с использованием 'struct' (MS VS 2k8) кажется, что по крайней мере некоторые компиляторы манипулируют по-разному в зависимости от используемого ключевого слова, поэтому лучше неположитесь на него, даже если это технически разрешено (о чем я не могу найти подтверждающую ссылку).

2 голосов
/ 01 февраля 2011

В C ++ структура - это класс.В частности:

Структура - это класс, определенный с помощью ключа класса struct.(ISO / IEC FDIS 14882: 1998 (E) 9-4)

Это означает, что ваш класс, который не был определен с struct, определенно не является структурой,Следовательно, ваше прямое объявление со структурным ключом класса ошибочно.Я не знаю ни одной части спецификации, которая позволяет предварительному объявлению использовать ключ класса, который явно неверен.Я уверен, что рассматриваемые снисходительные компиляторы одинаково относятся к структурам и классам и скрывают неверное объявление.В этом сценарии от компилятора может не потребоваться ошибка, но она не должна быть неожиданной.

0 голосов
/ 01 февраля 2011

MSVC10 выдает предупреждение, и на странице предупреждения указывается, что будет использоваться тип, указанный в определении.

http://msdn.microsoft.com/en-us/library/695x5bes.aspx

0 голосов
/ 01 февраля 2011

Я понятия не имею, является ли это неопределенным (или какой-либо другой категорией несоответствия) согласно стандарту C, но я знаю, что если у вас есть две единицы перевода, которые не согласны с тем, тип 'foo' объявлен как 'класс' или 'структура', например:

ТУ 1

struct foo;
void f(foo&) { ... }

ТУ 2

class foo { ... };
void f(foo&);

void g()
{
  foo x;
  f(x);
}

тогда, по крайней мере, некоторые компиляторы (особенно MSVC ++) будут по-разному обрабатывать имя f в каждой единице перевода, поэтому определение f в TU 1 не удовлетворяет ссылке на f в TU 2 и Вы получаете ошибку ссылки. Это происходит в реальной жизни, когда у вас есть заголовок A.h, который определяет класс A и должен ссылаться на классы B, C и D, но достаточно их предварительного объявления (так что, вполне разумно, не включает B.h и т. д.) - вам лучше использовать то же ключевое слово для тех предварительных объявлений, что и в реальных определениях!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...