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

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

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

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:2023):
    • 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/w/cpp/language/nested_types

Spec-Zone.ru

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