- •11. Инкапсуляция
- •12. Полиморфизм
- •13. Наследование
- •Управление доступом
- •Элементы класса
- •Элементы данных
- •Элементы функции
- •15. Перегрузка функций
- •16. Конструкторы и деструкторы Конструктор
- •Деструктор
- •17. Параметризированные конструкторы
- •18. Дружественные функции
- •19. Inline-функции
- •20. Передача объектов в функции
- •21. Возвращение объектов функциями
- •22. Массивы объектов
- •23. Указатели на объекты
- •24. Указатель this
- •25. Перегрузка операторов
- •26. Ссылки
- •27. Наследование и спецификаторы доступа
- •28. Конструкторы и деструкторы производных классов
- •29. Множественное наследование. Передача параметров в конструктор базового класса
- •30. Указатели и ссылки на производные типы
- •31. Виртуальные функции
- •32. Чисто виртуальные функции и абстрактные типы
- •33. Раннее и позднее связывание
- •35. Создание собственных операторов вставки и извлечения.
- •36. Форматирование ввода-вывода
- •37. Файловый ввод-вывод
- •38. Чтение и запись в текстовые файлы
- •39. Двоичные файлы
- •40. Функции-шаблоны
- •41. Классы-шаблоны
- •42. Использование пространства имён
- •43. Контейнерные классы
- •46. Основы обработки исключений
- •47. Идентификация типа во время исполнения (rtti)
- •49. Виртуальный базовый класс
35. Создание собственных операторов вставки и извлечения.
Создание операторов вставки
В С++ имеется лёгкий способ определения оператора вставки для создаваемых классов.
Общая форма функции вставки
ostream &operator<<(ostream &поток, тип_класса объект)
{
// характерный для типа код
return поток;
}
Обратим внимание на необходимость возвращать поток. Также является приемлимым и, более того, является общей практикой использовать в качестве параметра объект ссылку, а не сам объект. Во-первых, если объект является большим, то гораздо быстрее передать его адрес. Во-вторых, это предотвращает вызов деструктора объекта, когда функция возвращает результат.
В программе-примере перегруженная функция вставки не является членом класса three_d. Действительно, ни функция вставки, ни функция извлечения не могут быть членами класса. При перегрузке оператора вставки левым аргументом является поток, а правым аргументом – объект класса. Поэтому перегруженные операторы вставки не могут быть функциями-членами. Чтобы получить доступ к частным и защищённым членам класса оператор вставки должен быть другом класса. В качестве друга класса, для которого он определён, он имеет доступ к частным данным.
Пример
#include <iostream>
using namespace std;
class three_d {
int x, y, z;
public:
three_d(int a, int b, int c){ x=a; y=b; z=c; }
friend ostream &operator<<(ostream &stream, three_d obj);};
// вывод координат x, y, z (оператор вставки для three_d)
ostream &operator<<(ostream &stream, three_d obj)
{
stream << obj.x << ", ";
stream << obj.y << ", ";
stream << obj.z << "\n";
return stream;
}
int main()
{
three_d a(1,2,3), b(3,4,5), c(5,6,7);
cout << a << b << c;
return 0;
}
Перегрузка операторов извлечения
Для того, чтобы перегрузить оператор извлечения, используется тот же самый общий подход, что и для перегрузки операторов вставки.
Пример
// получение трёхмерных значений
istream &operator>>(istream &stream, three_d &obj)
{
cout <<
"Enter x y z values, separating each with a space: ";
stream >> obj.x >> obj.y >> obj.z;
return stream;
}
Общая форма экстрактора имеет вид:
istream &operator>>(istream &поток, тип_класса &obj)
{
// код экстрактора
return поток;
}
36. Форматирование ввода-вывода
Форматирование с помощью функций-членов ios
В заголовочном файле iostream определены флаги форматирования, которые можно всегда найти в справочниках. Эти значения используются для установки или сброса флагов, управляющих форматированием информации потоков.
Для установки флагов используется функция setf(), чей прототип имеет вид:
long setf(long flags);
Эта функция возвращает предыдущее значение флага, устанавливая его новое значение равным flags. При этом остальные флаги остаются неизменными.
Пример
stream.setf(ios::showpos);
Здесь stream является потоком, на который надо оказать воздействие.
Пример
#include <iostream>
using namespace std;
int main()
{
cout.setf(ios::showpos);
cout.setf(ios::scientific);
cout << 123 << " " << 123.23 << " ";
getchar();
return 0;
}
Данная программа выводит на экран
+123 +1.232300е+002
Для отключения флагов надо использовать функцию unsetf(). Она имеет следующий прототип:
long unsetf(long flags);
Функция возвращает значение предыдущей установки флага и сбрасывает флаги, определяемые параметром flags.
Иногда бывает полезным знать текущую установку флагов. Для этого служит функция flags(). Прототип:
long flags();
Кроме флага форматирования также можно установить ширину поля потока, символ для заполнения и число цифр после запятой. Для этого используются следующие функции:
int width(int len);
char fill(char ch);
int precision(int num);
Использование манипуляторов
Для использования манипуляторов с параметрами в программу необходимо включить файл iomanip.
Табл. 1
Манипулятор |
Назначение |
Ввод-вывод |
dec |
Ввод-вывод данных в десятичной форме |
ввод и вывод |
endl |
Вывод символа новой строки с передачей в поток всех данных из буфера |
вывод |
ends |
Вывод нулевого символа |
вывод |
flush |
Передача в поток содержимого буфера |
вывод |
hex |
Ввод-вывод данных в шестнадцатеричной системе |
ввод и вывод |
oct |
Ввод-вывод данных в восьмеричной системе |
ввод и вывод |
resetiosflags(long f) |
Сбрасывает флаги, указанные в f |
ввод и вывод |
setbase(int base) |
Устанавливает базу счисления равной параметру base |
вывод |
setfill(int ch)
|
Устанавливает символ заполнения равным ch |
вывод |
setiosflags(long f) |
Устанавливает флаги, указанные в f |
ввод и вывод |
setprecision(int p)
|
Устанавливает число цифр после запятой |
вывод
|
setw(int w)
|
Устанавливает ширину поля равной w |
вывод
|
ws |
Пропускает начальный символ разделитель |
ввод |
Пример
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
cout << setiosflags(ios::fixed);
cout << setprecision(2) << 1000.243 << endl;
cout << setw(20) << "Hello there.";
getchar();
return 0;
}
Программа выдаст на консоль:
1000.24
Hello there.