Spec-Zone.ru › C++

Вложенные классы

Объявление класса/структуры или объединения может находиться внутри другого класса. Такое объявление объявляет вложенный класс.

Пояснение

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

int x, y; // globals
class enclose // enclosing class
{
    // note: private members
    int x;
    static int s;
public:
    struct inner // nested class
    {
        void f(int i)
        {
            x = i; // Error: can't write to non-static enclose::x without instance
            int a = sizeof x; // Error until C++11,
                              // OK in C++11: operand of sizeof is unevaluated,
                              // this use of the non-static enclose::x is allowed.
            s = i;   // OK: can assign to the static enclose::s
            ::x = i; // OK: can assign to global x
            y = i;   // OK: can assign to global y
        }

        void g(enclose* p, int i)
        {
            p->x = i; // OK: assign to enclose::x
        }
    };
};

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

Определения членов вложенного класса вне класса размещаются в пространстве имён охватывающего класса:

struct enclose
{
    struct inner
    {
        static int x;
        void f(int i);
    };
};

int enclose::inner::x = 1;       // definition
void enclose::inner::f(int i) {} // definition

Вложенные классы можно предварительно объявить, а затем определить — либо в теле того же охватывающего класса, либо за его пределами:

class enclose
{
    class nested1;    // forward declaration
    class nested2;    // forward declaration
    class nested1 {}; // definition of nested class
};

class enclose::nested2 {}; // definition of nested class

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

class enclose
{
    struct nested // private member
    {
        void g() {}
    };
public:
    static nested f() { return nested{}; }
};

int main()
{
    //enclose::nested n1 = enclose::f(); // error: 'nested' is private

    enclose::f().g();       // OK: does not name 'nested'
    auto n2 = enclose::f(); // OK: does not name 'nested'
    n2.g();
}

Отчёты об ошибках

Следующие отчёты об ошибках, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применено к Поведение согласно опубликованной версии Правильное поведение
CWG 45 C++98 члены вложенного класса не могут
получать доступ к охватывающему классу и его друзьям
они имеют те же права доступа, что и
другие члены охватывающего класса
(также устраняет проблемы CWG № 8 и № 10)

Ссылки

  • Стандарт C++23 (ISO/IEC 14882:2024):
    • 11.4.12 Объявления вложенных классов [class.nest]
  • Стандарт C++20 (ISO/IEC 14882:2020):
    • 11.4.10 Объявления вложенных классов [class.nest]
  • Стандарт C++17 (ISO/IEC 14882:2017):
    • 12.2.5 Объявления вложенных классов [class.nest]
  • Стандарт C++14 (ISO/IEC 14882:2014):
    • 9.7 Объявления вложенных классов [class.nest]
  • Стандарт C++11 (ISO/IEC 14882:2011):
    • 9.7 Объявления вложенных классов [class.nest]
  • Стандарт C++98 (ISO/IEC 14882:1998):
    • 9.7 Объявления вложенных классов [class.nest]

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/nested_classes

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API