- •Объектно-ориентированное программирование:
- •Содержание
- •Новый тип данных – класс
- •1.2. Доступность компонентов класса
- •1.3. Конструктор и деструктор
- •1.4. Компоненты-данные и компоненты-функции
- •1.4.1. Данные – члены класса
- •1.4.2. Функции – члены класса
- •1.4.3. Константные компоненты-функции
- •1.4.4. Статические члены класса
- •Указатели на компоненты класса
- •1.5.1. Указатели на компоненты-данные
- •1.5.2.Указатели на компоненты-функции
- •1.6. Указатель this
- •1.7. Друзья классов
- •7.1. Дружественная функция
- •1.7.2. Дружественный класс
- •1.8. Определение классов и методов классов
- •2. Наследование
- •2.1. Определение производного класса
- •2.2. Конструкторы и деструкторы производных классов
- •2.3. Виртуальные функции
- •2.4. Абстрактные классы
- •2.5. Включение объектов
- •2.6. Включение и наследование
- •2.7. Множественное наследование
- •2.8. Локальные и вложенные классы
- •2.9. Пример программы для Microsoft Visual Studio
- •2.10. Упражнения
- •3. Перегрузка операций
- •3.1. Перегрузка унарных операций
- •3.2. Перегрузка бинарных операций
- •3.4. Перегрузка операции вызова функции
- •3.5. Перегрузка операции присваивания
- •3.6. Перегрузка операции new
- •3.7. Перегрузка операции delete.
- •3.8. Основные правила перегрузки операций
- •3.9. Примеры программ
- •4. Шаблоны функций и классов
- •4.1. Шаблоны функций
- •4.2. Шаблоны классов
- •4.3. Компонентные функции параметризованных классов
- •4.4. Примеры программ.
- •5. Обработка исключительных ситуаций
- •5.2. Получение дополнительной информации об исключении
- •5.3. Определение типа исключения
- •5.4. Иерархия исключений
- •5.5. Спецификация функций, обрабатывающих исключения
- •6. Потоковые классы
- •6.1. Библиотека потоковых классов
- •6.3. Стандартные потоки ввода-вывода
- •6.4. Форматирование
- •6.5. Манипуляторы
- •6.6. Ввод-вывод объектов пользовательских классов
- •6.7. Определение пользовательских манипуляторов
- •6.8. Пользовательские манипуляторы с параметрами
- •6.9. Использование макросов для создания манипуляторов
- •6.10. Состояние потока
- •6.11. Неформатированный ввод-вывод
- •6.12. Файловый ввод-вывод
- •7.1. Пространство имен
- •7.2. Динамическая идентификация типов
- •7.3. Безопасное приведение типа
- •8. Стандартная библиотека шаблонов
- •8.1. Введение в stl
- •Парадигму обобщенного программирования можно сформулировать следующим образом:
- •8.2. Итераторы
- •8.3. Классы-контейнеры
- •Iterator find(const key_type&k)
- •Iterator lower_bound(const key_type&k)
- •Iterator upper_bound(const key_type&k)
- •8.4. Контейнер vector
- •8.5. Многомерные массивы
- •8.6. Ассоциативные контейнеры
- •8.7. Объекты-функции
- •8.8. Алгоритмы
- •I. Немодифицирующие операции
- •II. Модифицирующие операции
- •III. Сортировка
- •IV. Работа с множествами
- •V. Минимумы и максимумы
- •VI. Перестановки
6.9. Использование макросов для создания манипуляторов
Для создания манипуляторов можно использовать макросы OMANIP(int), IMANIP(int), IOMANIP(int).
Эти макросы содержатся в файле <iomanip.h>
Ниже приведены примеры использования этих макросов.
а) манипулятор с одним параметром
ostream& w(ostream& out,int n)
{out.width(n);
//out<<setw(n);
return out;
}
OMANIP(int) w(int n)
{return OMANIP(int)(w,n);
}
Здесь две функции с именем w, вторая на первый взгляд кажется ненужной. Однако OMANIP(int) – это макрос, позволяющий определить манипулятор, который принимает параметры. Обнаружив в операции << манипулятор, компилятор использует вторую функцию для вызова первой.
б) манипулятор с двумя параметрами.
Проблема здесь в том, что макросы принимают только один параметр, так что для передачи нескольких параметров придется использовать структуру или класс. Например, для двух параметров:
struct Point
{
int n;
int m;
};
Перед использованием в манипуляторе Point нужно вызвать IOMANIPdeclare(Point). IOMANIPdeclare(Type) принимает только идентификатор, так что передача указателей или ссылок требует использования typedef.
#include<iostream.h>
#include<iomanip.h>
struct Point
{int x,y;};
IOMANIPdeclare(Point);
ostream& wp(ostream& out,Point p)
{out.width(p.x);
out.flags(ios::fixed);
out.precision(p.y);
return out;
}
OMANIP(Point) wp(int x,int y)
{Point p;
p.x=x;
p.y=y;
return OMANIP(Point)(wp,p);
}
6.10. Состояние потока
Каждый поток имеет связанное с ним состояние. Состояния потока описываются в классе ios в виде перечисления enum.
public:
enum io_state
{
goodbit,//нет ошибки 0Х00
eofbit,//конец файла 0Х01
failbit,//последняя операция не выполнилась 0Х02
badbit,//попытка использования недопустимой операции 0Х04
hardfail //фатальная ошибка 0Х08
};
Флаги, определяющие результат последней операции с объектом ios, содержатся в переменной state. Получить значение этой переменной можно с помощью функции int rdstate();
Кроме того, проверить состояние потока можно следующими функциями:
int bad(); возвращает 1, если badbit или hardfail
int eof(); возвращает, если eofbit
int fail(); возвращает, если failbit, badbit или hardfail
int good();возвращает, если goodbit
Если попытаться выполнить ввод из потока, который находится не в состоянии good(), то возвращается значение NULL. Если осуществляется чтение в переменную и происходит ошибка, то значение переменной не изменяется (предполагается, что переменная имеет стандартный тип, определенный в самом языке). Если операция >> используется для новых типов данных, то при её перегрузке необходимо предусмотреть соответствующие проверки.
Установить состояние потока в заданное значение можно функцией void clear(int s=0);
Эта функция устанавливает флаги ios::state в значение, заданное параметром s, не изменив при этом бита hardfail.
Пример 10.1.
#include<iostream.h>
#include<stdlib.h>
void main()
{int flags;
int k;
cin>>k;
flags=cin.rdstate();
if(flags) //если ошибка
if(flags& ios:badbit)
{cout<<”Ошибка\n”;
cin.clear(0);}
else{cerr<<”Эту ошибку нельзя исправить\n”;
abort();}
cout<<”Ввод без ошибок\n”;
cout<<k<<endl;
}
Пример 10.2.
#include<iostream.h>
#include<stdlib.h>
void main()
{int k;
cin>>k;
if(!cin)
if(cin.bad())
{cout<<”Oшибка\n”;
cin.clear(0);}
else
{cerr<<”Неисправимая ошибка\n”;
abort();}
cout<<”Ввод без ошибок\n”;
cout<<k<<endl;
}
Здесь используется перегруженная int operator!();
Результат операции – значение функции ios::fail().
Есть еще operator void*(), который возвращает 0, когда fail() возвращает 1, в противном случае возвращает указатель this на объект ios.
