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

Почему С++ не требует форвардных объявлений для членов класса?

У меня создалось впечатление, что все, что должно быть в С++, должно быть объявлено до использования.

На самом деле, я помню, что я читал, что это причина, по которой использование типов auto в возвращаемых типах недопустимо С++ 0x без чего-то вроде decltype: компилятор должен знать объявленный тип до, оценивая тело функции.

Представьте мое удивление, когда я заметил (после долгого времени), что следующий код на самом деле совершенно легален:

[Изменить: Изменен пример.]

class Foo
{
    Foo(int x = y);
    static const int y = 5;
};

Итак, теперь я не понимаю:

Почему компилятор не требует прямого объявления внутри классов, когда он требует их в других местах?

4b9b3361

Ответ 1

В стандарте говорится (раздел 3.3.7):

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

Это, вероятно, достигается за счет задержки обрабатывающих тел встроенных функций-членов до тех пор, пока не будет проведен анализ всего определения класса.

Ответ 2

Определения функций внутри тела класса обрабатываются так, как если бы они были фактически определены после определения класса. Таким образом, ваш код эквивалентен:

class Foo
{
    Foo();
    int x, *p;
};
inline Foo::Foo() { p = &x; }

Ответ 3

На самом деле, я думаю, вам нужно обратить вспять вопрос, чтобы понять его.

Почему С++ требует прямого объявления?

Из-за того, как работает С++ (включая файлы, а не модули), в противном случае нужно было бы дождаться всей единицы перевода, прежде чем вы сможете точно оценить, что это за функции. Здесь есть несколько недостатков:

  • время компиляции займет еще один хит
  • было бы почти невозможно предоставить какую-либо гарантию для кода в заголовках, так как любое введение более поздней функции могло бы аннулировать все это.

Почему класс отличается?

Класс по определению содержится. Это небольшая единица (или должна быть...). Поэтому:

  • существует небольшая проблема времени компиляции, вы можете дождаться окончания класса, чтобы начать анализ
  • нет никакого риска зависимого ада, поскольку все зависимости четко идентифицированы и изолированы.

Поэтому мы можем отбросить это раздражающее правило декларации forward для классов.

Ответ 4

Просто гадание: компилятор сохраняет тело функции и фактически не обрабатывает его до тех пор, пока объявление класса не будет завершено.

Ответ 5

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

Представьте себе реализацию класса в заголовке, если все должно быть объявлено заранее. я предполагаю, что, поскольку он связан, логичнее было записать язык как есть, вместо того, чтобы требовать, чтобы пользователь писал вперед в классе (или требуя определений отдельно от объявлений).