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

Классы (и структуры) могут быть объявлены внутри другого класса или даже внутри какого-либо метода. Такие классы называются вложенными.

Обычные вложенные классы

Если объявление класса расположено внутри другого класса, то такой класс можно скрыть от внешнего кода, добавив его в раздел private. Начиная со стандарта C++11, вложенный класс является другом внешнего класса, поэтому внутри вложенного класса мы имеем доступ:

  • к статическим членам внешнего класса, включая закрытые. Перед именем статического члена указывается название внешнего класса и оператор ::. Пример:
std::cout << A::z << ' ';
  • к обычным членам класса, включая закрытые, через экземпляр внешнего класса:
void A::B::print(A &o) {
   std::cout << o.y_ << std::endl;
}

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

friend class Название_внешнего_класса;

При определении методов вложенного класса отдельно от объявления класса, перед названием метода через оператор :: указываются названия внешнего и вложенного классов:

void A::B::func() { std::cout << "A::B::func() " << std::endl; }

Пример использования вложенного класса приведен в листинге 13.34.

Листинг 13.34. Вложенные классы

#include <iostream>

class A {                                // Внешний класс
private:
   class B {                             // Вложенный класс
      friend class A;
      int x_;
   public:
      B(int x) : x_(x) { }
      void func();
      void print(A &o);
   };

   B objB;
   int y_;
   static int k_;
public:
   A(int x, int y) : objB(x), y_(y) { }
   int getY() { return y_; }
   int getX() { return objB.x_; }        // friend class A;
   void test();

   static int z;
};

int A::z = 12;
int A::k_ = 14;
void A::B::func() { std::cout << "A::B::func() " << x_ << std::endl; }
void A::B::print(A &o) {
   // std::cout << y_ << std::endl;      // Нет доступа
   // error: invalid use of non-static data member 'A::y_'
   std::cout << A::z << ' ';             // OK (public static)
   std::cout << A::k_ << ' ';            // OK (private static)
   std::cout << o.y_ << std::endl;       // OK (private y_)
}
void A::test() {
   objB.func();
   objB.print(*this);
}

int main() {
   A obj(10, 20);
   obj.test();                           // A::B::func() 10
                                         // 12 14 20
   std::cout << obj.getY() << std::endl; // 20
   std::cout << obj.getX() << std::endl; // 10
   return 0;
}

Если вложенный класс объявлен общедоступным (public), то мы можем создать экземпляр вложенного класса, указав в качестве типа переменной название внешнего класса, после которого идет оператор :: и название вложенного класса. Например, изменим строку 4 из листинга 13.34:

private:

следующим образом:

public:

Теперь внутри функции main() мы можем создать экземпляр класса B:

A::B obj2(30);
obj2.func();       // A::B::func() 30

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

public:
   typedef B AB;

Доступ к вложенному классу через псевдоним внутри функции main() осуществляется так:

A::AB obj3(40);    // Внешний_класс::Псевдоним Объект(40);
obj3.func();       // A::B::func() 40

Учебник C++ (MinGW-W64)
Учебник C++ (MinGW-W64) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов