Программирование класс внутри класса

Объявления вложенных классов

Класс можно объявить в области другого класса. Такой класс называется «вложенным классом». Вложенные классы считаются в пределах область включающего класса и доступны для использования в этом область. Для обращения ко вложенному классу из области, отличной от непосредственно включающей его области, следует использовать полное имя.

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

// nested_class_declarations.cpp class BufferedIO < public: enum IOError < None, Access, General >; // Declare nested class BufferedInput. class BufferedInput < public: int read(); int good() < return _inputerror == None; >private: IOError _inputerror; >; // Declare nested class BufferedOutput. class BufferedOutput < // Member list >; >; int main()

BufferedIO::BufferedInput и BufferedIO::BufferedOutput объявляются в . BufferedIO Эти имена классов не видимы за пределами области класса BufferedIO . Однако объект типа BufferedIO не содержит объекты типа BufferedInput или BufferedOutput .

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

В предыдущем примере BufferedIO к перечислению IOError можно получить доступ непосредственно с помощью функций-членов во вложенных классах BufferedIO::BufferedInput или BufferedIO::BufferedOutput , как показано в функции good .

Вложенные классы объявляют только типы в пределах области класса. Они не создают объекты по вложенном классе. В предыдущем примере объявляется два вложенных класса, но не объявляются объекты этих типов классов.

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

// nested_class_declarations_2.cpp class C < public: typedef class U u_t; // class U visible outside class C scope typedef class V <>v_t; // class V not visible outside class C >; int main() < // okay, forward declaration used above so file scope is used U* pu; // error, type name only exists in class C scope u_t* pu2; // C2065 // error, class defined above so class C scope V* pv; // C2065 // okay, fully qualified name C::V* pv2; >

Права доступа во вложенных классах

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

Читайте также:  Home gate программирование пульта

Функции-члены во вложенных классах

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

// member_functions_in_nested_classes.cpp class BufferedIO < public: enum IOError < None, Access, General >; class BufferedInput < public: int read(); // Declare but do not define member int good(); // functions read and good. private: IOError _inputerror; >; class BufferedOutput < // Member list. >; >; // Define member functions read and good in // file scope. int BufferedIO::BufferedInput::read() < return(1); >int BufferedIO::BufferedInput::good() < return _inputerror == None; >int main()

В предыдущем примере для объявления имени функции используется синтаксис с полным именем типа . Объявление:

BufferedIO::BufferedInput::read() 

означает » read функция, являющаяся членом BufferedInput класса, который находится в область BufferedIO класса». Так как в этом объявлении используется синтаксис с полным именем типа, возможны конструкции следующей формы:

typedef BufferedIO::BufferedInput BIO_INPUT; int BIO_INPUT::read() 

Предыдущее объявление эквивалентно предыдущему, но вместо имен классов используется typedef имя.

Дружественные функции во вложенных классах

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

// friend_functions_and_nested_classes.cpp #include enum < sizeOfMessage = 255 >; char *rgszMessage[sizeOfMessage]; class BufferedIO < public: class BufferedInput < public: friend int GetExtendedErrorStatus(); static char *message; static int messageSize; int iMsgNo; >; >; char *BufferedIO::BufferedInput::message; int BufferedIO::BufferedInput::messageSize; int GetExtendedErrorStatus() < int iMsgNo = 1; // assign arbitrary value as message number strcpy_s( BufferedIO::BufferedInput::message, BufferedIO::BufferedInput::messageSize, rgszMessage[iMsgNo] ); return iMsgNo; >int main()

В следующем коде показана функция GetExtendedErrorStatus , объявленная в качестве дружественной функции. В функции, определенной в области видимости файла, сообщение копируется из статического массива в член класса. Обратите внимание, что для оптимальной реализации функции GetExtendedErrorStatus рекомендуется объявить ее следующим образом.

int GetExtendedErrorStatus( char *message ) 

В предыдущем интерфейсе несколько классов могут использовать службы этой функции, передав адрес памяти, в которую требуется скопировать сообщение об ошибке.

Источник

Программирование класс внутри класса

Вложенный класс (nested class) — это класс, определение которого находится внутри другого класса. Обычно вложенные классы применяются для описания таких сущностей, которые могут существовать только в рамках объекта внешнего класса, особенно когда внешний класс работает с набором объектов вложенного класса.

Рассмотрим небольшой пример. Допустим, нам надо определить для пользователя данные, которые описывают его учетную запись (логин, пароль):

#include 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>; int main() < Person tom; 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 их значения:

В функции main создаем один объект Person и передаем через конструктор данные в том числе для объекта Account:

Консольный вывод программы:

Name: Tom Email: tom@localhost.com Password: qwerty

В примере выше объекты Account нельзя создавать или использовать вне класса Person, так как класс Account является приватным. Однако мы можем также сделать его общедоступным и после этого обращаться к нему вне класса Person:

#include 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::coutprivate: std::string name; Account account; // переменная вложенного класса Account >; int main() < Person::Account account; Person bob; bob.print(); >

Теперь вложенный класс является публичным. Мы можем даже создать объекты этого класса и обращаться к его переменным и функциям, используя имя внешнего класса:

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

Источник

Программирование класс внутри класса

Классы могут быть вложенными (nested), то есть могут быть определены внутри других классов. Частным случаем вложенных классов являются внутренние классы (inner class). Например, имеется класс Person, внутри которого определен класс Account:

public class Program < public static void main(String[] args) < Person tom = new Person("Tom", "qwerty"); tom.displayPerson(); tom.account.displayAccount(); >> class Person < private String name; Account account; Person(String name, String password)< this.name = name; account = new Account(password); >public void displayPerson() < System.out.printf("Person \t Name: %s \t Password: %s \n", name, account.password); >public class Account < private String password; Account(String pass)< this.password = pass; >void displayAccount() < System.out.printf("Account Login: %s \t Password: %s \n", Person.this.name, password); >> >

Внутренний класс ведет себя как обычный класс за тем исключением, что его объекты могут быть созданы только внутри внешнего класса.

Внутренний класс имеет доступ ко всем полям внешнего класса, в том числе закрытым с помощью модификатора private. Аналогично внешний класс имеет доступ ко всем членам внутреннего класса, в том числе к полям и методам с модификатором private.

Ссылку на объект внешнего класса из внутреннего класса можно получить с помощью выражения Внешний_класс.this , например, Person.this .

Объекты внутренних классов могут быть созданы только в том классе, в котором внутренние классы опеределены. В других внешних классах объекты внутреннего класса создать нельзя.

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

public class Program < public static void main(String[] args) < Person tom = new Person("Tom"); tom.setAccount("qwerty"); >> class Person < private String name; Person(String name)< this.name = name; >public void setAccount (String password) < class Account< void display()< System.out.printf("Account Login: %s \t Password: %s \n", name, password); >> Account account = new Account(); account.display(); > >

Статические вложенные классы

Кроме внутренних классов также могут быть статические вложенные классы. Статические вложенные классы позволяют скрыть некоторую комплексную информацию внутри внешнего класса:

class Math < public static class Factorial< private int result; private int key; public Factorial(int number, int x)< result=number; key = x; >public int getResult() < return result; >public int getKey() < return key; >> public static Factorial getFactorial(int x) < int result=1; for (int i = 1; i return new Factorial(result, x); > >

Здесь определен вложенный класс для хранения данных о вычислении факториала. Основные действия выполняет метод getFactorial , который возвращает объект вложенного класса. И теперь используем классы в методе main:

public static void main(String[] args)

Источник

Оцените статью