- •Тема 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.6.Форматирование потока
Для управления форматированием ввода-вывода предусмотрены три вида средств: форматирующие функции, флагииманипуляторы. Все эти средства являются членами классаiosи потому доступны для всех потоков.
Рассмотрим вначале форматирующие функции-члены. Их всего три: width(), precision() и fill().
По умолчанию при выводе любого значения оно занимает столько позиций, сколько символов выводится. Функция width() позволяет задать минимальную ширину поля для вывода значения. При вводе она задает максимальное число читаемых символов. Если выводимое значение имеет меньше символов, чем заданная ширина поля, то оно дополняется символами-заполнителями до заданной ширины (по умолчанию - пробелами). Если же выводимое значение имеет больше символов, чем ширина отведенного ему поля, то поле будет расширено до нужного размера. Эта функция имеет следующие прототипы:
int width(int wide);
int width() const;
Функция с первым прототипом задает ширину поля wide, а возвращает предыдущее значение ширины поля. Функция со вторым прототипом возвращает текущее значение ширины поля. По умолчанию она равна нулю, то есть вывод не дополняется и не обрезается. В ряде компиляторов после выполнения каждой операции вывода значение ширины поля возвращается к значению, заданному по умолчанию.
Функция precision() позволяет узнать или задать точность (число выводимых цифр после десятичной точки), с которой выводятся числа с плавающей точкой. По умолчанию числа с плавающей точкой выводятся с точностью, равной шести цифрам. Функция precision () имеет следующие прототипы:
int precision(int prec);
int precision() const;
Функция с первым прототипом устанавливает точность в prec и возвращает предыдущую точность. Функция со вторым прототипом возвращает текущую точность.
Функция fill() позволяет прочесть или установить символ-заполнитель. Она имеет следующие прототипы:
char fill(char type ch);
char fill() const;
Функция с первым прототипом устанавливает ch в качестве текущего символа-заполнителя и возвращает предыдущий символ-заполнитель. Функция со вторым прототипом возвращает текущий символ-заполнитель. По умолчанию в качестве символа-заполнителя используется пробел.
Рассмотрим пример программы, в котором используются форматирующие функции:
# include <conio.h>
# include <iostream.h>
# include <stdio.h>
# include <math.h>
# include <iomanip.h>
void main()
{ double x;
cout.precision(4);
cout.fill(' ');
cout.width(10);
cout << "x";
cout.width(11);
cout <<"sqrt(x)";
cout.width(13);
cout <<"x^2\n\n";
cout.setf(ios::oct|ios::showbase);
cout.setf(ios::showpos|ios::left);
for (x=1.0; x<= 10; x++)
{
cout.width(10);
cout << x << " ";
cout.width(10);
cout << sqrt(x) << " ";
cout.width(10);
cout << x*x << '\n';
}
getch();
char* c="cool";
cout.width(10);
cout<<c;
cout.width(11);
cout<<c;
cout.width(11);
cout<<c;
getch();
}
Эта программа выводит на экран небольшую таблицу значений переменной x, ее квадратного корня и квадрата:
x sqrt(x) x^2
+1 +1 +1
+2 +1.414 +4
+3 +1.732 +9
+4 +2 +16
+5 +2.236 +25
+6 +2.449 +36
+7 +2.646 +49
+8 +2.828 +64
+9 +3 +81
+10 +3.162 +100
cool cool cool
С каждым потоком связан набор флагов, которые управляют форматированием потока. Они представляют собой битовые маски, которые определены в классеiosкак данные перечисления.
Флаги форматирования и их назначение приведены в табл. 11.3.
Таблица 11.3. Флаги форматирования и их назначение
Флаг |
Назначение |
hex |
Значения целого типа преобразуются к основанию 16 (как шестнадцатеричные) |
dec |
Значения целого типа преобразуются к основанию 10 |
oct |
Значения целого типа преобразуются к основанию 8 (как восьмеричные) |
fixed |
Числа с плавающей точкой выводятся в формате с фиксированной точкой (то есть nnn.ddd) |
scientific |
Числа с плавающей точкой выводятся в так называемой научной записи (то есть n.хххЕуу) |
showbase |
Выводится основание системы счисления в виде префикса к целому числовому значению (например, число 1FE выводится как 0x1FE) |
showpos |
При выводе положительных числовых значений выводится знак плюс |
uppercase |
Заменяет определенные символы нижнего регистра на символы верхнего регистра (символ "е" при выводе чисел в научной нотации на "Е" и символ "х" при выводе 16-ричных чисел на "X") |
left |
Данные при выводе выравниваются по левому краю поля |
right |
Данные при выводе выравниваются по правому краю поля |
internal |
Добавляются символы-заполнители между всеми цифрами и знаками числа для заполнения поля вывода |
skipws |
Ведущие символы-заполнители (знаки пробела, табуляции и перевода на новую строку) отбрасываются |
stdio |
Потоки stdout, stderr очищаются после каждой операции вставки |
unitbuf |
Очищаются все выходные потоки после каждой операции вставки в поток |
stdio |
Очищаются stdout, stderr после каждой операции вставки в поток |
Флаги left и right взаимно исключают друг друга. Флаги dec, oct и hex также взаимно исключают друг друга.
Прочесть текущие установки флагов позволяет функция-член flags() класса ios. Для этого используется следующий прототип этой функции:
long flags();
Функция flags() имеет и вторую форму, которая может использоваться для установки значений флагов. Для этого используется следующий прототип этой функции:
long flags(long fmtfl);
В этом случае битовый шаблон копирует fmtfl в переменную, предназначенную для хранения флагов форматирования. Функция возвращает предыдущие значения флагов. Поскольку эта форма функции меняет весь набор флагов, она применяется редко. Вместо нее используется функция-член setf() класса ios, которая позволяет установить значение одного или нескольких флагов. Она имеет следующие прототипы:
long setf (long mask);
long setf (long fmtfl, long mask);
Первая функция-член неявно вызывает функцию flags (mask | flags()) для установки битов, указанных параметром mask, и возвращает предыдущие значения флагов. Второй вариант функции присваивает битам, указанным параметром mask, значения битов параметра fmtfl, а затем возвращает предыдущие значения флагов.
Например, следующий вызов функции setf() устанавливает для потока cout флаги hex и uppercase:
cout.setf(ios::hex | ios::uppercase);
В качестве второго параметра функции setf() можно использовать следующие константы, определенные в классе ios:
static const long basefield; // = dec | oct | hex static const long adjustfield; // = left | right | internal static const long floatfield; // = scientific | fixed
Сбросить установленные флаги можно с помощью функции-члена unsetf() класса ios, имеющей следующий прототип:
void unsetf(long mask);
Она сбрасывает флаги, заданные параметром mask. Следующий пример демонстрирует некоторые флаги:
double d = 1.321e9; int n = 1024; void main()
{ // Вывести значения cout << "d = " << d << '\n' ; cout << "n = " << n << '\n'; // Изменить флаги и вывести значения снова cout.setf(ios::hex | ios::uppercase); cout.setf(ios::showpos); cout << "d = " << d << '\n' ; cout << "n = " << n << '\n'; }
При выполнении программа выводит на экран:
d = 1.321е+09 n = 1024 d = +1.321E+09 n = 400 |
Система ввода-вывода C++ предусматривает еще один способ форматирования потока. Этот способ основан на использовании манипуляторов ввода-вывода. Список манипуляторов и их назначение приведены в табл. 7. Манипуляторы ввода-вывода представляют собой просто вид функций-членов классаios, которые, в отличие от обычных функций-членов, могут располагатьсявнутриинструкций ввода-вывода. В связи с этим ими пользоваться обычно удобнее.
Таблица 11.4. Манипуляторы ввода-вывода и их назначение
Манипулятор |
Использование |
Назначение |
dec |
Ввод-вывод |
Устанавливает флаг dec |
endl |
Вывод |
Вставляет символ новой строки и очищает буфер |
ends |
Вывод |
Вставляет символ конца |
flush |
Вывод |
Очищает буфер потока |
hex |
Ввод-вывод |
Устанавливает флаг hex |
oct |
Ввод-вывод |
Устанавливает флаг oct |
resetiosflags (iosbase::long mask) |
Ввод-вывод |
Сбрасывает ios-флаги в соответствии с mask |
Setbase (int base) |
Ввод-вывод |
Задает основание системы счисления для целых (8, 10, 16) |
Setfill (int c) |
Ввод-вывод |
Устанавливает символ-заполнитель |
setiosflags (iosbase::long mask) |
Ввод-вывод |
Устанавливает ios-флаги в соответствии с mask |
setprecision (int n) |
Ввод-вывод |
Устанавливает точность чисел с плавающей точкой |
setw(int n) |
Ввод-вывод |
Устанавливает минимальную ширину поля |
ws |
Ввод |
Устанавливает пропуск символов-заполнителей |
За исключением setw(), все изменения в потоке, внесенные манипулятором, сохраняются до следующей установки.
Для доступа к манипуляторам с параметрами необходимо включить в программу стандартный заголовочный файл iomanip.h. При использовании манипулятора без параметров скобки за ним не ставятся, так как на самом деле он представляет собой указатель на функцию-член, который передается перегруженному оператору <<.
Рассмотрим пример, демонстрирующий использование манипуляторов.
#include < iostream.h > #include < iomanip.h > #include < math.h > void main() { double x; cout << setprecision(4); cout << setfill('0'); cout << " x sqrt(x) x^2\n\n"; for (x=1.0; x < 6.5; x++) { cout << setw(7) << x << " "; cout << setw(7) << sqrt(x) << " "; cout << setw(7) << x*x << "\n"; } }
Этот пример функционально полностью эквивалентен приведенному ранее (лишь несколько сокращен), но для управления форматом вывода использует манипуляторы, а не функции форматирования.
Манипулятор setw(),как и форматирующая функцияwidth(), может помочь избежать переполнения строки-приемника при вводе символьных строк:
const int SIZE = 50; . . . char array[SIZE]; cin>>setw(sizeof(array)); // Или cin.width(sizeof(array)); // Ограничивает число вводимых символов . . . // и позволяет избежать выхода за границу массива. cin >> array;