
- •Учебное пособие
- •Введение
- •Объектно-ориентированный подход
- •Объектно-ориентированное программирование Абстрактные типы данных
- •Базовые принципы объектно-ориентированного программирования
- •Простейший ввод и вывод
- •Объект cout
- •Манипуляторы hex и oct
- •Другие манипуляторы
- •Объект cin
- •Операторы для динамического выделения и освобождения памяти (new и delete)
- •Базовые конструкции объектно-ориентированных программ Объекты
- •Понятие класса
- •Конструктор копирования
- •Конструктор explicit
- •Указатели на компоненты класса
- •Встроенные функции (спецификатор inline)
- •Организация внешнего доступа к локальным компонентам класса (спецификатор friend)
- •Вложенные классы
- •Static-члены (данные) класса
- •Указатель this
- •Компоненты-функции static и const
- •Proxi-классы
- •Параметры ссылки
- •Независимые ссылки
- •Практические приемы ограничения числа объектов класса
- •Наследование (производные классы)
- •Конструкторы и деструкторы при наследовании
- •Виртуальные функции
- •Абстрактные классы
- •Виртуальные деструкторы
- •Множественное наследование
- •Виртуальное наследование
- •Перегрузка функций
- •Перегрузка операторов
- •Перегрузка бинарного оператора
- •Перегрузка унарного оператора
- •Дружественная функция operator
- •Перегрузка оператора []
- •Перегрузка оператора ()
- •Перегрузка операторов new и delete
- •Преобразование типа
- •Явные преобразования типов
- •Преобразования типов, определенных в программе
- •Шаблоны Параметризированные классы
- •Передача в шаблон класса дополнительных параметров
- •Шаблоны функций
- •Совместное использование шаблонов и наследования
- •Шаблоны класса и friend
- •Некоторые примеры использования шаблона класса Реализация smart-указателя
- •Классы поддерживающие транзакции
- •Задание значений параметров класса по умолчанию
- •Пространства имен
- •Ключевое слово using как директива
- •Ключевое слово using как объявление
- •Псевдоним пространства имен
- •Организация ввода-вывода
- •Состояние потока
- •Строковые потоки
- •Организация работы с файлами
- •Организация файла последовательного доступа
- •Создание файла произвольного доступа
- •Основные функции классов ios, istream, ostream
- •Основы обработки исключительных ситуаций
- •Перенаправление исключительных ситуаций
- •Исключительная ситуация, генерируемая оператором new
- •Генерация исключений в конструкторах
- •Задание собственной функции завершения
- •Спецификации исключительных ситуаций
- •Задание собственного неожиданного обработчика
- •Иерархия исключений стандартной библиотеки
- •Стандартная библиотека шаблонов (stl) Общее понятие о контейнере
- •Общее понятие об итераторе
- •Категории итераторов
- •Основные итераторы
- •Вспомогательные итераторы
- •Операции с итераторами
- •Контейнерные классы Контейнеры последовательностей
- •Контейнер последовательностей vector
- •Контейнер последовательностей list
- •Контейнер последовательностей deque
- •Ассоциативные контейнеры
- •Ассоциативный контейнер multiset
- •Ассоциативный контейнер set
- •Ассоциативный контейнер multimap
- •Ассоциативный контейнер map
- •Адаптеры контейнеров
- •Адаптеры stack
- •Адаптеры queue
- •Адаптеры priority_queue
- •Пассивные и активные итераторы
- •Алгоритмы
- •Алгоритмы сортировки sort, partial_sort, sort_heap
- •Алгоритмы поиска find, find_if, find_end, binary_search
- •Алгоритмы fill, fill_n, generate и generate_n
- •Алгоритмы equal, mismatch и lexicographical_compare
- •Математические алгоритмы
- •Алгоритмы работы с множествами
- •Алгоритмы swap, iter_swap и swap_ranges
- •Алгоритмы copy, copy_backward, merge, unique и reverse
- •Примеры реализации контейнерных классов Связанные списки
- •Реализация односвязного списка
- •Реализация двусвязного списка
- •Реализация двоичного дерева
- •Литература
- •Вопросы по курсу ооп
- •220013, Минск, п.Бровки, 6.
Вложенные классы
Один класс может быть объявлен в другом классе, в этом случае внутренний класс называется вложенным:
class ext_class
{ class int_cls
{
};
public:
};
Класс int_class является вложенным по отношению к классу ext_class (внешний).
Доступ к компонентам вложенного класса, имеющим атрибут private, возможен только из функций вложенного класса и из функций внешнего класса, объявленных со спецификатором friend во вложенном классе.
#include "iostream.h"
class cls1 // внешний класс
{ class cls2 // вложенный класс
{ int b; // все компоненты private для cls1 и cls2
cls2(int bb) : b(bb){} // конструктор класса cls2
};
public: // public секция для cls1
int a;
class cls3 // вложенный класс
{ int c; // private для cls1 и cls3
public: // public-секция для класса cls3
cls3(int cc): c(cc) {} // конструктор класса cls3
};
cls1(int aa): a(aa) {} // конструктор класса cls
};
void main()
{ cls1 aa(1980); // верно
cls1::cls2 bb(456); // ошибка cls2 cannot access private
cls1::cls3 cc(789); // верно
cout << aa.a << endl; // верно
cout << cc.c << endl; // ошибка 'c' : cannot access private member
// declared in class 'cls1::cls3'
}
В приведенном тексте программы инструкция cls1::cls2 bb(456) является ошибочной, так как объявление класса cls2 и его компонента находятся в секции private. Для устранения ошибки при описании объекта bb необходимо изменить атрибуты доступа для класса cls2 следующим образом:
public:
class cls2
{ int b; // private-компонента
public:
cls2(int bb) : b(bb){}
};
Пример доступа к private-компонентам вложенного класса из функций внешнего класса, объявленных со спецификатором friend, приводится ниже.
#include "iostream.h"
class cls1 // внешний класс
{ int a;
public:
cls1(int aa): a(aa) {}
class cls2; // неполное объявление класса
void fun(cls1::cls2); // функция получает объект класса cls2
class cls2 // вложенный класс
{ int c;
public:
cls2(int cc) : c(cc) {}
friend void cls1::fun(cls1::cls2); // ф-ция, дружественная классу cls1
int pp(){return c;}
};
};
void cls1::fun(cls1::cls2 dd) {cout << dd.c << endl << a;}
void main()
{ cls1 aa(123);
cls1:: cls2 cc(789);
aa.fun(cc);
}
Внешний класс cls1 содержит public-функцию fun(cls1::cls2 dd), где dd есть объект, соответствующий классу cls2, вложенному в класс cls1. В свою очередь в классе cls2 имеется friend-функция friend void cls1::fun(cls1::cls2 dd), обеспечивающая доступ функции fun класса cls1 к локальной компоненте с класса cls2.
#include "iostream.h"
#include "string.h"
class ext_cls // внешний класс
{ int gd; // год рождения
double zp; // з/плата
class int_cls1 // первый вложенный класс
{ char *s; // фамилия
public:
int_cls1(char *ss) // конструктор 1-го вложенного класса
{ s=new char[20];
strcpy(s,ss);
}
~int_cls1() // деструктор 1-го вложенного класса
{ delete [] s;}
void disp_int1() {cout << s<<endl;}
};
public:
class int_cls2 // второй вложенный класс
{ char *s; // фамилия
public:
int_cls2(char *ss) //конструктор 2-го вложенного класса
{ s=new char[20];
strcpy(s,ss);
}
~int_cls2() // деструктор 2-го вложенного класса
{ delete [] s;}
void disp_int2() {cout << s << endl;}
};
// public функции класса ext_cls
ext_cls(int god,double zpl):gd(god),zp(zpl){}// конструктор внешнего
// класса
int_cls1 *addr(int_cls1 &obj){return &obj;} // возврат адреса объекта obj
void disp_ext()
{ int_cls1 ob("Иванов"); // создание объекта вложенного класса
addr(ob)->disp_int1(); // вывод на экран содержимого объекта ob
cout <<gd<<’ ’<< zp<<endl;
}
};
void main()
{ ext_cls ext(1980,230.5);
// ext_cls::int_cls1 in1("Петров"); // неверно, т.к. int_cls1 имеет
// атрибут private
ext_cls::int_cls2 in2("Сидоров");
in2.disp_int2();
ext.disp_ext(); //
}
В результате выполнения программы получим:
Сидоров
Иванов
230.5
В строке in2.disp_int2() (main функции) для объекта вложенного класса вызывается компонента-функция ext_cls::int_cls2::disp_int2() для вывода содержимого объекта in2 на экран. В следующей строке ext.disp_ext() вызывается функция ext_cls::disp_ext(), в которой создается объект вложенного класса int_cls1. Затем, используя косвенную адресацию, вызывается функция ext_cls::int_cls1::disp_int1(). Далее выводятся данные, содержащиеся в объекте внешнего класса.