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_types

Spec-Zone.ru

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