- •Тема 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. Гибридные базы данных
- •Рекомендуемая литература
11.4.Переадресация ввода-вывода
Можно переназначить имена cinилиcoutфайловым потокам. Это позволяет легко проводить отладку ввода-вывода, переадресовывая ввод-вывод вместо файла на экран. Следующий пример демонстрирует эту возможность:
#include < iostream.h > #include < fstream.h > int main(int argc, char* argv[])
{ char str[80]; // Создаем файловый поток: ofstream ofs; // Если в командной строке задан аргумент … cout << "Введите имя и фамилию:\n"; cin.getline(str, sizeof(str)); if (argc > 1){ // Открываем файл с заданным именем ofs.open(argv[1]); // Если файл успешно открыт … if (ofs) // переадресовываем вывод cout = ofs; } cout << "Привет, " << str << '!' << endl; return 0; }
Если при запуске программы в командной строке задано имя файла, то вывод осуществляется в этот файл, в противном случае - на экран терминала.
Здесь можно отметить очевидные преимущества стандартной библиотеки ввода-вывода:
1. Безопасность.Так как имеются перегруженные версии операции сдвига operator<< (), правая операция для примера:
#include < iostream.h > cout << i <<' ' << name << '\n';
- всегда будет выполнена. Функция cout<< i вызывает operator<< (int), a cout<< name вызывает operator<< (const char*). Следовательно, использование стандартных потоков являетсябезопасным по типам данных.
2. Расширяемость для новых типов.Другим преимуществом стандартных потоков С++ является то, что определенные пользователем типы данных могут быть без труда в них встроены.
Рассмотрим класс Data, данные которого необходимо печатать:
struct Data { int x; char* y;};
Все, что нужно сделать, это перегрузить операцию << для нового типа Data. Соответствующая функция operator<< () может быть реализована так:
ostream &operator<< (ostream & out, const Data & р)
{ return out << p.x << ' ' << p.у; } После этого станет возможно осуществлять вывод:
#include < iostream.h > struct Data {int x; char* y; Data (int x, char* y){this->x = x; this->y = y;} };
ostream &operator<< (ostream & out, const Data & p){ return out << p.x <<' '<< p.y; }
void main(){ Data p(1, "Error"); cout << p<< '\n'; }
11.5. Операции помещения в поток и извлечения из потока
Вывод в поток выполняется с помощью операции вставки (в поток), которая является перегруженной операцией сдвига влево << . Левым ее операндом является объект потока вывода. Правым операндом может являться любая переменная, для которой определен вывод в поток (то есть переменная любого встроенного типа или любого определенного пользователем типа, для которого она перегружена). Например, оператор cout << "Hello!\n"; приводит к выводу в предопределенный поток cout строки "Hello!".
Операция << возвращает ссылку на объект типа ostream, для которого она вызвана. Это позволяет строить цепочки вызовов операции вставки в поток, которые выполняются слева направо:
int i = 5; double d = 2.08; cout << "i = " << i << ", d = " << d << '\n';
Эти операторы приведут к выводу на экран следующей строки:
i = 5, d = 2.08 |
Операция вставки в поток поддерживает следующие встроенные типы данных: char, short, int, long, char* (рассматриваемый как строка), float, double, long double, void*:
ostream& operator<< (short n); ostream& operator<< (unsigned short n); ostream& operator<< (int n); ostream& operator<< (unsigned int n); ostream& operator<< (long n); ostream& operator<< (unsigned long n) ; ostream& operator<< (float f); ostream& operator<< (double f); ostream& opera to r<< (long double f) ; ostream& operator<< (const void *p);
Целочисленные типы форматируются в соответствии с правилами, принятыми по умолчанию, если они не изменены путем установки различных флагов форматирования. Тип void* используется для отображения адреса:
int i; // Отобразить адрес в 16-ричной форме: cout << &i;
Отметим, что перегрузка не изменяет нормального приоритета выполнения операции <<, поэтому можно записать
cout << "sum =" << x+y << "\n";
без круглых скобок. Однако, в случае
cout << (x & y) << "\n";
круглые скобки нужны.
Для ввода информации из потока используется операция извлечения, которой является перегруженная операция сдвига вправо >>. Левым операндом операции >> является объект класса istream , который также является и результатом операции. Это позволяет строить цепочки операций извлечения из потока, выполняемых слева направо. Правым операндом может быть любой тип данных, для которого определен поток ввода.
istream & operator>>(short& n); istream & operator>>(unsigned short& n); istream & operator>>(int& n); istream & operator>>(unsigned int& n); istream & operator>>(long& n); istream & operator>>(unsigned long& n); istream & operator>>(float& f); istream & operator>>(double& f); istreaai& operator>>(long double& f); istream & operator>>(void*& p);
По умолчанию операция >> пропускает символы-заполнители (по умолчанию - пробельные символы), затем считывает символы, соответствующие типу заданной переменной. Пропуск ведущих символов-заполнителей устанавливается специально для этого предназначенным флагом форматирования. Рассмотрим следующий пример:
int i; double d; cin >> i >> d;
Последний оператор приводит к тому, что программа пропускает ведущие символы-заполнители и считывает целое число в переменную i. Затем она игнорирует любые символы-заполнители, следующие за целым числом, и считывает переменную с плавающей точкой d.
Для переменной типа char* (рассматриваемой как строка) оператор >> пропускает символы-заполнители и сохраняет следующие за ними символы, пока не появится следующий символ-заполнитель. Затем в указанную переменную добавляется нуль-символ '\n'.