Вложенный класс (nested class) — это класс, определение которого находится внутри другого класса. Обычно вложенные классы применяются для описания таких сущностей, которые могут существовать только в рамках объекта внешнего класса, особенно когда внешний класс работает с набором объектов вложенного класса.
Рассмотрим небольшой пример. Допустим, нам надо определить для пользователя данные, которые описывают его учетную запись (логин, пароль):
#include <iostream> class Person { private: std::string name; class Account // вложенный класс { public: Account(const std::string& p_email, const std::string& p_password) { email = p_email; password = p_password; } std::string email; std::string password; }; Account account{"", ""}; // переменная вложенного класса Account public: Person(const std::string& p_name, const std::string& p_email, const std::string& p_password) { name = p_name; account = Account(p_email, p_password); } void print() { std::cout<<"Name: " << name << "\n" << "Email: " << account.email << "\n" << "Password: " << account.password << std::endl; } }; int main() { Person tom{"Tom", "tom@localhost.com", "qwerty"}; tom.print(); }
Здесь класс Person представляет класс пользователя. А данные его учетной записи выделены в отдельный класс - Account. Класс Account определен как приватный. Таким образом, обращаться к этому классу мы сможем только внутри класса Person.
class Account // вложенный класс { public: Account(std::string p_email, std::string p_password) { email = p_email; password = p_password; } std::string email; std::string password; };
Во вложенных классах также можно использовать специафикаторы доступа. В данном случае поля email и password и конструктор определены как публичные, общедоступные, чтобы их можно было использовать в классе Person вне класса Account. Тем более, что так как класс Account - приватный, эти поля все равно недоступны из вне класса Person.
Для хранения данных аккаунта конкретного объекта Person определена переменная account:
Account account{"", ""}; // переменная вложенного класса Account
В данном случае она инициализируется начальными данными - пустыми строками для email и пароля.
В конструкторе класса Person получаем данные для email и пароля и на их основе создаем объект Account:
account = Account(p_email, p_password);
Поскольку поля email и password - публичные, мы можем обратиться в функциях класса Person, например, выведем в функции print их значения:
void print() { std::cout<<"Name: " << name << "\n" << "Email: " << account.email << "\n" << "Password: " << account.password << std::endl; }
В функции main создаем один объект Person и передаем через конструктор данные в том числе для объекта Account:
Person tom{"Tom", "tom@localhost.com", "qwerty"}; tom.print();
Консольный вывод программы:
Name: Tom Email: tom@localhost.com Password: qwerty
В примере выше объекты Account нельзя создавать или использовать вне класса Person, так как класс Account является приватным. Однако мы можем также сделать его общедоступным и после этого обращаться к нему вне класса Person:
#include <iostream> class Person { public: class Account // вложенный класс { public: Account(const std::string& p_email, const std::string& p_password) { email = p_email; password = p_password; } std::string email{}; std::string password{}; }; Person(const std::string& p_name, const Account& p_account) { name = p_name; account = p_account; } void print() { std::cout<<"Name: " << name << "\n" << "Email: " << account.email << "\n" << "Password: " << account.password << std::endl; } private: std::string name; Account account{"", ""}; // переменная вложенного класса Account }; int main() { Person::Account account{"bob@somemail.com", "qwerty"}; Person bob{"Bob", account}; bob.print(); }
Теперь вложенный класс является публичным. Мы можем даже создать объекты этого класса и обращаться к его переменным и функциям, используя имя внешнего класса:
Person::Account account{"bob@somemail.com", "qwerty"};
Функции вложенного класса могут напрямую ссылаться на статические члены внешнего класса, а также на любые другие типы, определенные во внешнем классе. Доступ к другим членам внешнего класса можно получить из вложенного класса стандартными способами: через объект класса, указатель или ссылку на объект класса. При этом функции вложенного класса могут обращаться в том числе к приватным переменным и константам, которые определены во внешнем классе.