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

Видимость внутреннего члена в классе

В соответствии со стандартом С++

9.2 [class.mem]:

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

Итак, приведенный ниже код должен компилироваться, и действительно, он

struct Foo{
     Foo()
     {
        Bar bar; // Bar is fully visible here, even though it defined later
     }
     //void f(Bar){} // But NOT VISIBLE if used as a function parameter
     struct Bar{};
};

int main()
{
    Foo foo;
}

Live on Coliru

Однако, если я раскомментирую строку, которая определяет функцию-член void Foo::f(Bar), тогда код не скомпилируется с ошибкой

ошибка: "Бар" не был объявлен

Снова повторив стандарт, действительно кажется, что параметры функции не считаются местами, где класс считается полным. Однако это не имеет никакого смысла. Можете ли вы пролить свет, почему я не могу использовать Bar в параметре функции (но в противном случае может полностью использовать его внутри функцию без каких-либо проблем) до ее полного определения?

4b9b3361

Ответ 1

Во всех случаях, перечисленных в 9.2 [class.mem], зная, что тип может быть отложен до полного определения класса. Мы можем видеть это обоснование, перечисленное в отчет о дефекте 643: Использование decltype в спецификации члена класса, в котором говорится:

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

Как T.C. указывает, что есть также проблемы поиска, связанные с отчет о дефекте 325: когда аргументы по умолчанию разобраны? и отчет о дефекте 1352. В более поздней части также упоминается одна и та же методика, позволяющая отложить парсинг до завершения класса:

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

Ответ 2

Из стандарта 03, 3.4.1/8 (поиск неквалифицированного имени):

Имя, используемое в определении функции-члена (9.3) класса X, следующего за функциями declarator-id 29) объявляется одним из следующих способов:

- перед его использованием в блоке, в котором он используется, или в закрывающем блоке (6.3), или

- должен быть членом класса X или быть членом базового класса X (10.2) или

- если X является вложенным классом класса Y (9.7), должен быть членом Y или быть членом базового класса Y (этот поиск применяется в свою очередь к Ys, охватывающим классы, начиная с самого внутреннего охватывающего класса), 30) или

- если X является локальным классом (9.8) или является вложенным классом локального класса, то до определения класса X в блоке включая определение класса X, или

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