- •Тема 1.Понятие технологии программирования (2 часа). 3
- •Тема 2. Основные концепции ооп (2 часа). 7
- •Тема 3. Конструкторы и деструкторы (2 часа). 12
- •Тема 5. Дружественные функции (friend functions) (2 часа) 32
- •Тема 6. Обработка исключительных ситуаций (2 часа) 44
- •Тема 8. Производные классы (2 часа) 76
- •Тема 9. Виртуальные функции (2 часа) 83
- •Тема 10. Множественное наследование. Производные классы векторов (2 часа) 90
- •Тема 12. Шаблоны функций и классов. 128
- •Тема 14. Применение оо-подхода в базах данных 148
- •Тема 1.Понятие технологии программирования (2 часа).
- •1.1. Предмет изучения курса ооп
- •1.2. Исторический экскурс
- •1.3. Основные технологии программирования
- •1.4. Заключение
- •Тема 2. Основные концепции ооп (2 часа).
- •2.1. Объекты и классы
- •2.1.1.Понятие класса объектов
- •2.1.2. Основные характеристики состояния класса
- •2.1.3. Понятие инкапсуляции свойств объекта
- •2.1.4. Структура глобальной памяти класса и глобальные методы класса
- •2.1.5. Интерфейс класса
- •2.1.6. Функции-члены класса
- •2.2. Понятие наследования (Inheritance)
- •2.3. Понятиеполиморфизма
- •Тема 3. Конструкторы и деструкторы (2 часа).
- •3.1. Для чего нужны конструкторы
- •3.2. Использование конструкторов «по умолчанию»
- •3.3. Использование деструкторов
- •3.4. Демонстрация последовательности работы конструкторов и деструкторов
- •3.5. Конструктор копирования
- •3.6. Определение операции присваивания
- •3.6.1. Пример использования конструктора копирования.
- •3.7.1. Краткий обзор библиотеки stl
- •3.7.2. Вектора
- •3.8. Inline-подстановка
- •4.1. Перегрузка операторов
- •4.1.1. Пример на перегрузку операторов
- •4.1.2. Общие принципы перегрузки операторов
- •4.1.3. Бинарные и Унарные Операции
- •4.2. Пример с перегрузкой операторов
- •Тема 5. Дружественные функции (friend functions) (2 часа)
- •5.1. Примеры использования дружественных функций
- •5.2. Особенности перегрузки префиксной и постфиксной форм унарных операций
- •5.3. Статические члены данных
- •5.4. Перегрузка операторов new, new[], delete, delete[]
- •Void* operator new(size_t размер){ код оператора
- •Void operator delete(void* p){ код оператора }
- •Void* operator new[](size_t размер){ код оператора return указатель_на_память; }
- •Void operator delete[](void* p){ код оператора }
- •Тема 6.Обработка исключительных ситуаций(2 часа)
- •6.1. Применение try, catch, throw
- •6.2. Синтаксис и семантика генерации и обработки исключений
- •6.3. Обработка исключений
- •6.4. Обработка исключений при динамическом выделении памяти
- •6.5. Функции, глобальные переменные и классы поддержки механизма исключений
- •6.6. Конструкторы и деструкторы в исключениях
- •7.1 Строковые типы
- •7.1.1. Преобразования, определяемые классом
- •7.1.2. Встроенный строковый тип
- •7.1.3 Класс string
- •7.2. Пример строкового класса с перегруженными операторами и дружественными функциями
- •Тема8.Производные классы (2 часа)
- •8.1. Определение производного класса
- •8.2. Правила использования атрбутов доступа
- •8.3. Конструкторы и деструкторы производных классов
- •Тема 9. Виртуальные функции (2часа)
- •9.1. Определение виртуальных методов
- •9.2. Абстрактные классы
- •9.3. Таблицы виртуальных методов (функций)
- •9.4. Выводы
- •Тема 10. Множественное наследование. Производные классы векторов (2 часа)
- •10.1. Множественное наследование
- •10.2. Отношения между классами
- •10.2.3. Ассоциация
- •10.2.4. Агрегирование
- •10.2.5. Наследование
- •10.3. Библиотека графических объектов (пример)
- •10.3.1. Динамический полиморфизм и наследование интерфейсов
- •10.3.2.Абстрактные классы
- •10.3.3. Множественное наследование в библиотеке графичкских фигур.
- •10.3.4. Иерархия классов библиотеки графичкских фигур
- •10.3.5. Таблица наследования
- •10.3.6. Диаграмма модулей
- •10.3.7.Директивы препроцессора
- •10.4. Производные классы векторов
- •10.5. Операции над векторами
- •11.1. Потоковый ввод-вывод
- •11.1.1. Классы потоков
- •11.1.2. Стандартные потоки
- •11.2.Опрос и установка состояния потока
- •11.3.Перегрузка операций извлечения и вставки в поток
- •11.4.Переадресация ввода-вывода
- •11.5. Операции помещения в поток и извлечения из потока
- •11.6.Форматирование потока
- •11.7.Файловый ввод-вывод с использованием потоков
- •11.8.Бесформатный ввод-вывод
- •11.9.Часто применяемые функции библиотеки ввода / вывода
- •11.10.Файлы с произвольным доступом
- •11.11. Буферизация
- •11.12. Заключение
- •Тема 12. Шаблоны функций и классов.
- •12.1 Шаблоны функций
- •12.2. Шаблоны классов
- •12.3. Размещение определений шаблонов в многомодульных программах
- •12.4. Полиморфные вектора
- •13.1 Область видимости
- •13.1.1. Локальная область видимости
- •13.2. Глобальные объекты и функции
- •13.2.1. Объявления и определения
- •13.2.2. Несколько слов о заголовочных файлах
- •13.3. Локальные объекты
- •13.3.1. Автоматические объекты
- •13.3.2. Регистровые автоматические объекты
- •13.3.3. Статические локальные объекты
- •13.4. Динамически размещаемые объекты
- •13.4.1. Динамическое создание и уничтожение единичных объектов
- •13.5. Определения пространства имен а
- •Тема 14. Применение оо-подхода в базах данных
- •14.1. Реляционные базы данных
- •14.2 Объектно-ориентированные базы данных (ообд)
- •14.3. Гибридные базы данных
- •Рекомендуемая литература
3.4. Демонстрация последовательности работы конструкторов и деструкторов
Программа
/* Демонстрация последовательности, в которой вызываются конструкторы и деструкторы. */
#include<iostream.h>
// описание класса CreateAndDestroy
class CreateAndDestroy
{
public:
CreateAndDestroy(int value) // конструктор
{
data = value;
cout << " Object " << data << " constructor";
}
~CreateAndDestroy() // деструктор
{
cout << " Object " << data << " destructor" << endl;
}
private:
int data;
};
CreateAndDestroy first(1); // глобальный объект
void create(void); //прототип функции
void main ()
{
cout << "\t(global object) " << endl;
CreateAndDestroy second(2); // локальный объект
cout << "\t(local auto object in main) " << endl;
static CreateAndDestroy third(3); // статический объект
cout << "\t(local static object in main) " << endl;
create(); // вызов функции создания объектов
CreateAndDestroy fourth(4); // локальный объект
cout << "\t(local auto object in main) " << endl;
}
// Функция создания объектов
void create(void)
{
CreateAndDestroy fifth(5); // локальный объект
cout << "\t(local auto object in create) " << endl;
static CreateAndDestroy sixth(6); // статический объект
cout << "\t(local static object in create) " << endl;
CreateAndDestroy seventh(7); // локальный объект
cout << "\t(local auto object in create) " << endl;
}
Результаты выполнения программы
Object 1 constructor (global object)
Object 2 constructor (local auto object in main)
Object 3 constructor (local static object in main)
Object 5 constructor (local auto object in create)
Object 6 constructor (local static object in create)
Object 7 constructor (local auto object in create)
Object 7 destructor
Object 5 destructor
Object 4 constructor (local auto object in main)
Object 4 destructor
Object 2 destructor
Object 6 destructor
Object 3 destructor
Object 1 destructor
3.5. Конструктор копирования
По умолчанию, при инициализации одного объекта другим, С++ выполняет побитовое копирование.Это означает, что один объект становится точной копией другого.
Памятка
Инициализация возникает в 3хслучаях.
когда один объект инициализирует другой, (операция присваивания)
когда объект передаётся в функцию по значению и
когда объект служит в качестве возвращаемого значения функции.
Понятие копирования
Здесь мы поговорим об одном из аспектов внутреннего функционирования программ, написанных на C++ - о копировании. Копирование в программах на C++ происходит, прямо или косвенно, буквально на каждом шагу. Причем, не всегда с первого взгляда очевидно, где происходит копирование, а где нет.
Мы начнем с рассмотрения синтаксиса интересующего нас предмета, а затем попробуем углубиться в его осмысление.
Определение конструктора копий
Конструктор копий используется для создания новых объектов из уже существующих. Это означает, что, так же как для других конструкторов, новый объект еще не существует к моменту его вызова. Однако только конструктору копий объект передается как аргумент по ссылке. Итак, синтаксис конструктора копий прост. Конструктор копий произвольного класса X выглядит так:
Х(const X&) ; // конструктор копий класса Х |
Так как конструктор копий - это все таки конструктор, то он должен иметь имя, совпадающее с именем класса (не забывайте с учетом регистра символов). Назначение конструктора копий - дублирование объекта-аргумента для построения нового объекта. Одно из основных правил: если аргумент не должен изменяться, то его следует передавать как константу. В то же время, если аргумент не описан как константа, то нельзя копировать объекты-константы. Переменный объект всегда можно передать как постоянный аргумент, но не наоборот.
Вторая часть объявления аргумента, X, проста: копируется объект того же самого типа. Аргумент в целом читается как "постоянная ссылка на X". Ссылка существенна по нескольким соображениям. В первую очередь потому, что при передаче адреса объекта не создается копия вызывающего объекта (в отличие от передачи аргумента по значению). Если вам чудится здесь какой-то подвох, то будьте внимательны.
Работа конструктора копий - создание ранее не существовавшего объекта из уже существующего, а передача по значению (без использования операции получения адреса) требует создания копии аргумента, значит мы получаем бесконечную рекурсию. Точнее: при передаче объекта по значению создается его копия, если это произойдет в конструкторе копий, то он будет вызывать сам себя, пока не исчерпает все ресурсы системы.
Вот несколько правил, которым надо следовать при объявлениях конструктора копий:
Имя функции точно совпадает с именем класса.
Аргумент объявляется постоянным, что позволяет принимать как постоянные, так и переменные аргументы.
Тип аргумента является типом класса.
Аргумент передается по ссылке, т. е. с помощью операции получения адреса.
Написание конструктора копий является чрезвычайно ответственным поступком. Явное определение конструктора копий вызывает изменения в работе программы. Пока мы не пытались переопределить конструктор копий, исправно работал конструктор, порождаемый компилятором автоматически. Этот конструктор создавал "фотографические" копии объектов, то есть копировал значения абсолютно всех данных-членов, в том числе и ненулевые значения указателей, представляющие адреса динамических областей памяти. С момента появления переопределённой версии конструктора копий, вся работа по реализации алгоритмов копирования возлагается на программиста. Впрочем, заставить конструктор копий копировать объекты совсем несложно. Создадим класс, описывающий точку на плоскости.
Код:
class POINT { public: POINT() { X=0; Y=0; } //конструктор по умолчанию POINT(int a, int b) { X=a; Y=b; } //еще конструктор POINT(const POINT& Pixel) { X=Pixel.X; Y=Pixel.Y; } //конструктор //копирования int X; //координаты точки int Y; }; |
Как видим, этот конструктор копий просто копирует значения координат. В принципе, если бы мы его не определили, то компилятор создал бы его сам, причем в этом случае он делал бы то же самое. Но конструктор, создающий подобные копии объектов, скорее всего, окажется непригодным для работы с объектами, содержащими в качестве членов указатели или ссылки. Предположим, что класс содержит указатели. Тогда адреса, содержащиеся в указателях объекта-оригинала и объекта-копии, будут идентичны. Это означает, что два объекта будут указывать на одну и ту же область памяти, что, как правило, очень опасно. Это мы рассмотрим подробно несколько позднее.
В переопределяемом конструкторе копий (а в классе он может быть только один) можно реализовывать разнообразные алгоритмы распределения памяти. Здесь всё зависит от программиста. Итак, обычно, конструктор копий, созданный компилятором, удовлетворителен при следующих обстоятельствах:
Среди членов класса нет указателей (*).
Среди членов класса нет ссылок (&).
В этом случае вполне разумно использовать конструктор, построенный компилятором. В текст определения класса в этом случае полезно поместить соответствующий комментарий о том, что конструктор копии не определен вполне сознательно. Вообще говоря, комментарии относительно рассматриваемых четырех членов уместны в каждом классе. Вот пример:
Код:
class X { public: Х(); // конструктор по умолчанию virtual ~X(); // виртуальный деструктор // Конструктор копии и операция присваивания не определены // намеренно. Класс содержит только данные, размещаемые // в стеке, поэтому предопределенных конструктора копий //и операции присваивания достаточно. private: int data; char moreData; float no_Pointers; }; |
Если хотя бы одно из названных условий не выполняется, то следует определить как конструктор копий, так и операцию присваивания.