- •Список литературы по модулю
- •История языка C++
- •Основные особенности C++
- •Простые расширения языка C
- •Объявление переменных ссылочного типа
- •Инициализация и использование ссылок
- •Ссылки в формальных параметрах функций
- •Ссылки как возвращаемые значения функций
- •Константные ссылки
- •Объявление класса
- •Секции в объявлении класса
- •Пример: секции в объявлении класса
- •Объявление полей
- •Определения статических полей
- •Объявление методов
- •Виртуальные и абстрактные методы
- •Объявление конструкторов
- •Пример: объявление конструкторов
- •Создание объектов в динамической памяти
- •Создание массивов в динамической памяти
- •Удаление объектов и массивов
- •Объявление деструктора
- •Пример: объявление деструктора
- •Объекты в автоматической памяти
- •Пример: автоматический вызов деструктора
- •Пример: автоматический вызов деструктора (продолжение)
- •Объекты в глобальной памяти
- •Объекты в полях других объектов
- •Пример: объекты в полях других объектов
- •Проблема копирования объектов
- •Объявление конструктора копий
- •Перегруженная операция присваивания
- •Основной способ наследования в C++
- •Пример: одиночное наследование
- •Переопределение методов
- •Пример: переопределение методов
- •Динамическое приведение типов
- •Пример: динамическое приведение типов не всегда допустимо
- •Пример: динамическое приведение типов
- •private- и protected-наследование
- •Наследование от нескольких базовых классов
- •Иерархия наследования и классы противоречия
- •Неоднозначности в противоречивых иерархиях
- •Разрешение неоднозначностей
- •Основная проблема противоречивых иерархий
- •Виртуальное наследование
- •Пример: виртуальное наследование
- •Понятие шаблона
- •Типовые формальные параметры шаблона
- •Нетиповые формальные параметры шаблона
- •Шаблонные формальные параметры шаблона
- •Значения параметров шаблона по умолчанию
- •Зависимые идентификаторы в шаблоне
- •Инстанциация шаблонов
- •Выведение фактических параметров при инстанциации шаблона функции
- •Требования к фактическим параметрам шаблонов
- •Специализация шаблона функции
- •Пример: специализация шаблона функции
- •Пример: перегрузка имеет больший приоритет, чем специализация
- •Cпециализация шаблона класса
- •Пример: специализация шаблона класса
- •Частичная специализация шаблона класса
- •Вычисления во время компиляции
- •Пример: возведение числа в степень
- •Понятие перегрузки операций
- •Ассортимент перегружаемых операций
- •Перегрузка операции присваивания
- •Операция присваивания возвращает левое значение
- •Составные операции присваивания
- •Перегрузка бинарных арифметических операций
- •Перегрузка операций сравнения
- •Перегрузка операций с помощью функций
- •Перегрузка унарных операций
- •Перегрузка операции приведения типа
- •Исключения
- •Оператор throw
- •Пример: оператор throw
- •Синтаксис try- и catch-блоков
- •Пример: перехват исключения std::bad_alloc
- •Жизненный цикл объектов-исключений
- •Пример 1: жизненный цикл объектов-исключений
- •Пример 2: жизненный цикл объектов-исключений
- •Пример 3: жизненный цикл объектов-исключений
- •Пример: уничтожение автоматических объектов в процессе передачи исключения в catch-блок
- •Перехват исключений в инициализаторах конструкторов
- •Пример: перехват исключений в инициализаторах конструкторов
- •Спецификатор throw в заголовках функций
- •Пример 1: спецификатор throw
- •Пример 2: спецификатор throw
- •Спецификатор throw и переопределение виртуальных методов
- •Создание классов исключений
- •Пример: создание классов исключений
Перегрузка операций с помощью функций
Базовые
сведения
Обобщённое программирова- ние
Перегрузка
операций
Введение
Присваивание
Бинарные
операции
Унарные опе-
рации
Операция ()
Исключения
Перегруженные операции могут иметь операнды разных типов. Это полезно, например, при реализации операции умножения матрицы на скалярное значение:
const Matrix & operator * ( int k) const ;
Однако, использование такой операции возможно только в случае, когда матрица является первым операндом. Чтобы справиться с этой проблемой, в C++ разрешена перегрузка операций с помощью функций. Например, в нашем случае функция умножения скалярного значения на матрицу может выглядеть как
const Matrix & operator * ( int k , const Matrix &m) { return m * k;
}
Следует иметь в виду, что хотя бы один операнд функции, осуществляющей перегрузку операций, должен быть объектом класса. Это гарантирует невозможность перегрузки операций над встроенными типами.
Перегрузка операций «&&» и «||»
Базовые
сведения
Обобщённое программирова- ние
Перегрузка
операций
Введение
Присваивание
Бинарные
операции
Унарные опе-
рации
Операция ()
Исключения
Операции «&&» и «||» могут быть перегружены точно так же, как и другие бинарные арифметические операции:
const A& operator && ( const A & other ) const ; const A& operator || ( const A & other ) const ;
Однако, перегрузка операций «&&» и «||» не рекомендуется. Дело в том, что эти операции применительно к встроенным типам данных вычисляют свой второй операнд не всегда.
Эта их особенность широко используется в программировании, т.е. любой программист ожидает, что они будут работать именно по этой схеме.
Перегруженные версии этих операций всегда будут вычислять оба операнда. Тем самым, их использование будет контринтуитивно, что обязательно приведёт к ошибкам в программах.
75 / 99
Перегрузка операции «[ ]»
Базовые
сведения
Обобщённое программирова- ние
Перегрузка
операций
Введение
Присваивание
Бинарные
операции
Унарные опе-
рации
Операция ()
Операция «[ ]» перегружается следующим образом:
тип1 & operator [] ( тип2 index );
Операция возвращает ссылку, что даёт возможность использовать её результат в левой части операции присваивания. К сожалению, таким образом перегруженную операцию невозможно применять к константным объектам. Поэтому принято определять ещё и специальную версию операции «[ ]» для константных объектов:
const тип1 & operator [] ( тип2 index ) const ;
Исключения
Естественно, в этом случае необязательно, чтобы операция возвращала ссылку. Поэтому, если «тип1» допускает дешёвое копирование, от ссылки можно избавиться. Например,
double operator [] ( int index ) const ;
Отметим, что операция «[ ]» не может быть перегружена с
помощью функции.
76 / 99
Перегрузка унарных операций
Базовые
сведения
Обобщённое программирова- ние
Перегрузка
операций
Введение
Присваивание
Бинарные
операции
Унарные опе-
рации
Операция ()
Исключения
Унарные операции перегружаются по одной из приведённых схем (далее «@» – некоторый знак операции):
class A
{
... |
|
|
|
|
|
тип operator@ |
(); |
// |
с |
помощью |
метода |
... |
|
|
|
|
|
}; |
|
|
|
|
|
тип operator@ (A |
& obj ); |
// |
с |
помощью |
функции |
Исключение составляют постфиксные ++ и --. Чтобы их отличать от префиксных инкремента и декремента, они имеют дополнительный фиктивный параметр типа int:
class A |
|
|
{ |
|
|
... |
|
|
A& operator ++ |
( int ); |
|
... |
|
|
}; |
|
|
A& operator ++ (A |
& obj , int ); |
77 / 99 |
Перегрузка операций «*» и «->»
Базовые
сведения
Обобщённое программирова- ние
Перегрузка
операций
Введение
Присваивание
Бинарные
операции
Унарные опе-
рации
Операция ()
Исключения
Перегрузка операций «*» и «->» позволяет использовать объекты класса так, как если бы они были указателями:
class A
{
...
тип & operator * (); тип operator -> ();
...
};
тип & operator * (A &a );
Особенностью операции «->» является тот факт, что она последовательно применяется к своему же возвращаемому значению до тех пор, пока не получится указатель. Т.е., например, если в классе A операция «->» возвращает ссылку на объект класса B, а в классе B операция «->» возвращает указатель на объект класса C, то применение «->» к переменной x типа A открывает доступ к полям и методам объекта класса C.
Пример: перегрузка операции «->»
Базовые |
1 |
|
|
||
сведения |
2 |
|
Обобщённое |
3 |
|
|
||
программирова- |
4 |
|
ние |
||
5 |
||
Перегрузка |
||
6 |
||
операций |
||
|
||
Введение |
7 |
|
Присваивание |
8 |
|
Бинарные |
9 |
|
операции |
||
10 |
||
Унарные опе- |
||
|
||
рации |
11 |
|
Операция () |
12 |
|
Исключения |
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
|
21 |
|
|
22 |
struct C { int field ; };
struct B { C c;
C* operator -> ();
};
C* B :: operator -> () { return &c; }
struct A { B b;
B& operator -> ();
};
B& A :: operator -> () { return b; }
int main ()
{
Ax;
x-> field = 666; return 0;
} |
79 / 99 |
Перегрузка операции «&»
Базовые
сведения
Обобщённое программирова- ние
Перегрузка
операций
Введение
Присваивание
Бинарные
операции
Унарные опе-
рации
Операция ()
Исключения
Перегрузка операции «&» позволяет вместо адреса объекта возвращать всё, что угодно (например, «умный» указатель, т.е. объект с перегруженными операциями «*» и «->», осуществляющий подсчёт ссылок на объект и автоматическое его удаление при уничтожении последней ссылки):
class A
{
...
тип operator & ();
...
};
тип operator & (A &a );
Впрочем, перегрузка этой операции не рекомендуется, т.к. может привести к трудноуловимым ошибкам в коде. Вместо её перегрузки рекомендуется определить метод, который делает то же самое, но не экранирует стандартную реализацию «&»:
тип address_of (); |
80 / 99 |