- •Тема 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.8.Бесформатный ввод-вывод
Когда файл открывается в текстовом режиме, происходит следующее:
при вводе каждая пара символов '\r' +' \n' (возврат каретки + перевод строки) преобразуется в символ перевода строки ('\n');
при выводе каждый символ перевода строки ('\n') преобразуется в пару '\r' +'\n' (возврат каретки + перевод строки).
Это не всегда удобно. Если необходимо использовать файл вывода для последующего ввода в программу (возможно, другую), лишние байты информации ни к чему. С этой целью система ввода-вывода предоставляет возможность осуществления бесформатного ввода-вывода, то есть записи и чтения двоичной информации (иногда говорят - сырых данных). Для осуществления ввода-вывода в двоичном режиме нужно включить флагios::binary в параметр open_mode, передаваемый конструктору потока или функции open(). Чтение двоичной информации из файла осуществляется функцией read(), которая имеет следующие прототипы:
istream & read(char* s, int n); istream & read(unsigned char* s, int n);
Здесь параметр s задает буфер для считывания данных, а параметр n - число читаемых символов.
Запись двоичных данных осуществляет функция-член write():
ostream& write(const char * s, int n); ostream& write(const unsigned char * s, int n);
Эта функция получает n символов из буфера, адрес которого задан параметром s, и вставляет их в поток вывода. Рассмотрим пример.
#include< iostream.h > #include< fstream.h > void main() { int x = 255; char str[80] = "Тестирование двоичного ввода-вывода."; // Открываем файл для вывода в двоичном режиме ofstream ofs("Test.dat"); if (!ofs) { cout << "Файл не открыт.\n"; return; } ofs.write((char*)&x, sizeof(int)); ofs.write((char*)&str, sizeof(str)); ofs.close(); // Открываем файл для вывода в двоичном режиме ifstream ifs("Test.dat"); if (!ifs) { cout << "Файл не открыт.\n"; return; } ifs.read((char*)&x, sizeof(int)); ifs.read((char*) str, sizeof(str)); cout << x << '\n' << str << '\n'; }
11.9.Часто применяемые функции библиотеки ввода / вывода
Помимо уже описанных функций, библиотека ввода-вывода C++ содержит широкий набор различных функций. Здесь мы приведем лишь некоторые, наиболее часто употребляемые из них. Большинство этих функций используется для бесформатноговвода-вывода.
Для извлечения символа из потока можно использовать функцию-член get() потока istream . Она имеет следующие прототипы:
int get(); istream & get(signed char*, int len, char delim= '\n'); istream & get(unsigned char*, int len, char delim= '\n'); istream & get(unsigned char &); istream & get(signed char &); istream & get(streambuf &, char delim= '\n');
Функция get() в первой форме возвращает код прочитанного символа или -1, если встретился конец файла ввода (ctrl/z).
Приведем пример использования функции get ():
#include < iostream.h > void main(){ char ch; cout << "Введите число. " << "Для завершения ввода нажмите < ENTER >:"; while (cin.get(ch)){ // Проверка на код клавиши < ENTER > if (ch = = '\n') break; } return; }
Для вставки символа в поток вывода используется функция put() с прототипом ostreaiu& put(char ch). Функция get () может также использоваться для чтения строки символов. В этом случае используются ее варианты, в которых эта функция извлекает из входного потока символы в буфер str, пока не встретится символ-ограничитель delim(по умолчанию - перевод строки) или не будет прочитано (len-1) символов, или не будет прочитан признак конца файла. Сам символ-ограничитель не извлекается из входного потока.
Ввиду того, что функция get() не извлекает из входного потока символ-ограничитель, она используется редко. Гораздо чаще используется функция getline(), которая извлекает из входного потока символ-ограничитель, но не помещает его в буфер. Она имеет следующие прототипы:
istream & getline (char* str, int len, char delim); istream & getline(char * str, int len);
Здесь параметры имеют те же назначения, что и в функции get().
Функция gcount() (с прототипом int gcount()const;) возвращает число символов, извлеченных из потока последней операцией бесформатного ввода (то есть функцией get(), getline() или read()).
Рассмотрим пример, в котором используются две последние функции:
#include < iostream.h > void main(){ char *name; int len = 100; int count = 0; name = new char[len]; cout << "Введите свое имя:"; cin.getline(name, len); count = cin.gcount(); // Уменьшаем значение счетчика на 1, так как // getline() не помещает ограничитель в буфер cout << "\nЧисло прочитанных символов: " << count - 1; }
Для того, чтобы пропустить при вводе несколько символов, используется функция ignore():
istream & ignore(int n = l, int delim = EOF);
Эта функция игнорирует вплоть до n символов во входном потоке. Пропуск символов прекращается, если она встречает символ-ограничитель, которым по умолчанию является символ конца файла. Символ-ограничитель извлекается из входного потока.
Функция peek(), имеющая прототип int peek(), позволяет "заглянуть" во входной поток и узнать следующий вводимый символ. При этом сам символ из потока не извлекается.
С помощью функции putback() (с прототипом istream &putback(char ch);) можно вернуть символ ch в поток ввода.
При выполнении вывода данные не сразу записываются в файл, а временно хранятся в связанном с потоком буфере, пока он не заполнится. Функция flush() позволяет вызвать принудительную запись в файл до заполнения буфера.
Она неявно используется манипулятором endl. Этот манипулятор вставляет в поток символ перевода строки и очищает буфер. Таким образом, оператор
cout << endl; эквивалентен следующим:
cout << '\n'; cout.flush();
Функция rdbuf() позволяет получить указатель на связанный с потоком буфер. Эта функция имеет прототипstreambuf* rdbuf() const;
Наконец, функция setbuf() с прототипом void setbuf(char*buf, int n) позволяет связать с потоком другой буфер. Здесь buf - указатель на другой буфер длины n.