
- •1.2 Философские замечания
- •1.3 Процедурное программирование
- •1.4 Модульное программирование
- •1.5 Абстракция данных
- •1.6 Пределы абстракции данных
- •1.7 Объектно-ориентированное программирование
- •1.8 Концепции объектно-ориентированного программирования
- •1.8.1 Инкапсуляция
- •1.8.2 Полиморфизм
- •1.8.3 Наследование
- •1.10 Несколько полезных советов
- •2.2 Перегрузка функций
- •2.3 Перегрузка операторов
- •2.4 Наследование
- •2.5 Конструкторы и деструкторы
- •2.7 Два новых типа данных
- •Глава 3. Классы и объекты
- •3.1 Параметризованные конструкторы
- •3.2 Дружественные функции
- •3.3 Значения аргументов функции по умолчанию
- •3.3.1 Корректное использование аргументов по умолчанию
- •3.4 Взаимосвязь классов и структур
- •3.5 Связь объединений и классов
- •3.6 Анонимные объединения
- •3.7 Inline-функции
- •3.7.1 Создание inline-функций внутри класса
- •3.8 Передача объектов в функции
- •3.9 Возвращение объектов функциями
- •3.10 Присваивание объектов
- •3.11 Конструктор копирования
- •3.12 Массивы объектов
- •3.12.1 Инициализация массивов объектов
- •3.12.2 Создание инициализированных и неинициализированных массивов
- •3.13 Указатели на объекты
- •3.14 Статические члены класса
- •Глава 4. Перегрузка функций и операторов
- •4.1 Перегрузка конструкторов
- •4.2 Локализация переменных
- •4.3 Локализация создания объектов
- •4.4 Перегрузка функций и неопределенность
- •4.5 Определение адреса перегруженной функции
- •4.6 Указатель this
- •4.7 Перегрузка операторов
- •4.8 Дружественная функция-оператор
- •4.9 Ссылки
- •4.9.1 Параметры-ссылки
- •4.9.2 Передача ссылок на объекты
- •4.9.3 Возврат ссылок
- •4.9.4 Независимые ссылки
- •4.9.5 Использование ссылок для перегрузки унарных операторов
- •4.10 Перегрузка оператора []
- •4.11 Создание функций преобразования типов
- •Глава 5. Наследование, виртуальные функции и полиморфизм
- •5.1 Наследование и спецификаторы доступа
- •5.1.1 Спецификаторы доступа
- •5.1.2 Спецификатор доступа при наследовании базового класса
- •5.1.3 Дополнительная спецификация доступа при наследовании
- •5.2 Конструкторы и деструкторы производных классов
- •5.3 Множественное наследование
- •5.4 Передача параметров в базовый класс
- •5.5 Указатели и ссылки на производные типы
- •5.6 Ссылки на производные классы
- •5.7 Виртуальные функции
- •5.8 Для чего нужны виртуальные функции?
- •5.9 Чисто виртуальные функции и абстрактные типы
- •5.10 Виртуальный базовый класс
- •5.11 Раннее и позднее связывание
- •Глава 6. Подсистема динамического выделения памяти
- •6.1 Введение в обработку исключений
- •6.1.1 Перехват всех исключений
- •6.2 Работа с памятью с помощью new и delete
- •6.3 Размещение объектов
- •6.4 Перегрузка new u delete
- •7.1.1 Потоки
- •7.3 Создание собственных операторов вставки и извлечения
- •7.3.1 Создание операторов вставки
- •7.3.2 Перегрузка операторов извлечения
- •7.4 Форматирование ввода/вывода
- •7.4.1 Форматирование с помощью функций-членов класса ios
- •7.4.2 Использование манипуляторов
- •7.5 Создание собственных функций-манипуляторов
- •7.5.1 Создание манипуляторов без параметров
- •7.5.2 Создание манипуляторов с параметрами
- •7.6 Файловый ввод/вывод
- •7.6.1 Открытие и закрытие файлов
- •7.6.2 Чтение и запись в текстовые файлы
- •7.6.3 Двоичный ввод/вывод
- •7.6.4 Определение конца файла
- •7.6.5 Произвольный доступ
- •Глава 8. Ввод/вывод в массивы
- •8.1 Классы ввода/вывода в массивы
- •8.2 Создание потока вывода
- •8.3 Ввод из массива
- •8.4 Использование функций-членов класса ios
- •8.5 Потоки ввода/вывода в массивы
- •8.6 Произвольный доступ в массив
- •8.7 Использование динамических массивов
- •8.8 Манипуляторы и ввод/вывод в массив
- •8.9 Собственные операторы извлечения и вставки
- •8.10 Форматирование на основе массивов
- •Глава 9. Шаблоны и библиотека stl
- •9.1 Функции-шаблоны
- •9.2 Функции с двумя типами-шаблонами
- •9.3 Ограничения на функции-шаблоны
- •9.4 Классы-шаблоны
- •9.5 Пример с двумя типами-шаблонами
- •9.6 Обзор библиотеки stl
- •9.7 Класс vector
- •9.7 Класс string
- •9.8 Класс list
4.11 Создание функций преобразования типов
Иногда необходимо создать класс таким образом, чтобы иметь возможность свободно использовать его в смешанных выражениях с данными других типов. Хотя перегруженные функции-операторы могут обеспечить смешанное использование типов, иногда достаточно простого преобразования типов. В таких случаях можно использовать функцию преобразования типа, преобразующую тип класса в другой тип, совместимый с остальными членами выражения. Общая форма функции преобразования типа имеет вид:
operator(тип)() {return значение;}
Здесь тип является целевым типом, к которому преобразуется класс, а значение представляет собой значение класса после преобразования. Функция преобразования должна быть членом класса, для которого она определяется.
Чтобы проиллюстрировать создание функции преобразования типа, используем класс point еще раз. Предположим, что необходимо преобразовать объект point в целое число таким образом, чтобы оно могло использоваться в целочисленном выражении. Допустим, это преобразование будет представлять собой произведение трех координат. Для его выполнения можно определить функцию преобразования следующим образом:
operator int() { return x*у*z; }
Ниже приведена программа, иллюстрирующая работу этой функции преобразования:
#include <iostream.h>
class point
{
int x, у, z; // трехмерные координаты
public:
point(int a, int b, int c) { x=a; y=b, z=c; }
point operator+(point op2);
operator int() { return x*y*z; }
};
point point::operator+(point op2)
{
point temp(0, 0, 0);
temp.x = x+op2.x; temp.у = y+op2.y; temp.z = z+op2.z;
return temp; }
int main()
{
point a(1, 2, 3), b(2, 3, 4);
cout << b+100; // вывод 124 из-за преобразования к int
cout << "\n";
return 0;
}
Как иллюстрирует данная программа, когда объект point используется в целочисленном выражении, таком как cout << b+100, используется функция преобразования объекта. В этом случае функция преобразования возвращает значение 24, которое затем прибавляется к 100.
Глава 5. Наследование, виртуальные функции и полиморфизм
Наследование и полиморфизм лежат в основе объектно-ориентированного программирования. С помощью наследования можно создать общий класс, определяющий общие черты совокупности объектов. Этот класс может наследоваться другими более специфическими классами, каждый из которых добавляет что-то свое.
Есть еще одна причина, по которой наследованию придается такая важность: с его помощью поддерживается полиморфизм во время выполнения программы. С помощью полиморфизма реализуется принцип «один интерфейс — множество методов».
В C++ полиморфизм поддерживается как на этапе исполнения программы, так и на этапе компиляции. В качестве примера полиморфизма на этапе компиляции можно указать перегрузку операторов и функций. Но как бы ни была полезна перегрузка операторов и функций, с их помощью нельзя решить все задачи, возникающие в объектно-ориентированном программировании. Поэтому в C++ также используют полиморфизм времени выполнения программы, для чего используются производные классы и виртуальные функции. Связанные с ними вопросы обсуждаются в этой главе. Начнем главу с подробного рассмотрения наследования.