- •Тема 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.7.2. Вектора
Встроенное в C++ понятие вектора было разработано так, чтобы обеспечить максимальную эффективность выполнения при минимальном расходе памяти. Оно также является весьма универсальным инструментом для построения средств более высокого уровня (особенно когда используется совместно с указателями). Можно, конечно, возразить, что для типа vector из стандартной библиотекиSTL(StandartTemplateLibrary) размер вектора должен задаваться как константа, и что нет проверки выхода за границы вектора и т.д. Ответ на подобные возражения таков: "Вы можете запрограммировать это сами". Давайте посмотрим, действительно ли оправдан такой ответ. Другими словами, проверим средства абстракции языка C++, попытавшись реализовать эти возможности для векторных типов, которые мы создадим сами, и посмотрим, какие с этим связаны трудности, каких это требует затрат, и насколько получившиеся векторные типы удобны в обращении.
class vector
{
int* v;
int sz;
public:
vector(int); // конструктор
~vector(); // деструктор
int size() {return sz};
void set_size(int);
int& operator[](int);
int& elem(int i) {return v[i]};
};
Функция sizeвозвращает число элементов вектора, таким образом, индексы должны лежать в диапазоне 0 ... size()-1. Функцияset_sizeсделана для изменения этого размера,elemобеспечивает доступ к элементам без проверки индекса, аoperator[]дает доступ с проверкой границ.
Идея состоит в том, чтобы класс сам был структурой фиксированного размера, управляющей доступом к фактической памяти вектора, которая выделяется конструктором вектора с помощью распределителя свободной памяти new:
vector::vector(int s)
{
if (s<=0) error("не правильный размер вектора");
sz = s;
v = new int[sz];
}
Тепрь вы можете описывать вектора типа vector почти столь же элегантно, как и вектора, встроенные в сам язык:
vector v1(100);
vector v2(nelem*2-4);// nelem – какое-то заданное число
Операцию доступа можно определить как
int& vector::operator[](int i)
{
if(i<0 || sz<=i) error("индекс выходит за границы вектора");
return v[i];
}
Правый операнд логической операции || (ИЛИ) вычисляется только тогда, когда это необходимо, то есть если вычисление левого операнда дало ноль. Возвращение ссылки обеспечивает то, что запись [] может использоваться с любой стороны операции присваивания:
v1[x] = v2[y];
Напомню, что функция ~vector - это деструктор, она неявно вызывается, когда объект класса выходит из области видимости.
vector::~vector()
{
delete v;
}
он будет, с помощью операции delete, освобождать пространство, выделенное конструктором, потому, когдаvectorвыходит из области видимости, все его пространство возвращается обратно в память для дальнейшего использования. Со встроеным классомvector мы еще встретимся позже.
3.8. Inline-подстановка
Если часто повторяется обращение к очень маленькой функции, то вы можете начать беспокоиться о стоимости вызова функции. Обращение к функции-члену не дороже обращения к функции не члену с тем же числом параметров (надо помнить, что функция-член всегда имеет хотя бы один параметр), и вызовы функций в C++ примерно столь же эффективны, сколь и в любом языке. Однако для слишком маленьких функций может встать вопрос о накладных расходах на обращение. В этом случае можно рассмотреть возможность спецификации функции как inline-подставляемой. Если вы поступите таким образом, токомпилятор сгенерирует для функции соответствующий код в месте ее вызова. Семантика вызова не изменяется. Если, например,size иeleminline-подставляемые, то
vector s(100);
//...
i = s.size();
x = elem(i-1);
порождает код, эквивалентный
//...
i = 100;
x = s.v[i-1];
Вы можете указать, что вы хотите, чтобы функция была inline- подставляемой, поставив ключевое слово inline, или, для функции-члена, просто включив определение функции в описание класса, как это сделано в предыдущем примере для size() и elem().
При хорошем использовании inline-функции резко повышают скорость выполнения и уменьшают размер объектного кода. Однако, inline-функции запутывают описания и могут замедлить компиляцию, поэтому, если они не необходимы, то их желательно избегать. Чтобы inline- функция давала существенный выигрыш по сравнению с обычной функцией, она должна быть очень маленькой.
ТЕМА 4. ПЕРЕГРУЗКА ОПЕРАТОРОВ С++ (2 часа)
Перегрузка операторов. Приведение типов. Пример с перегрузкой операторов.