Правила перегрузки операций
- Нельзя определить новый лексический символ для операции.
- Нельзя изменить приоритет, арность (т.е. количество аргументов) и ассоциативность операций.
- Нельзя перегрузить операцию для стандартных типов данных.
- Нельзя перегружать операции . :: .* ?: sizeof typeid.
- Операции = [] () -> можно перегружать только как методы.
- Не рекомендуется перегружать операции , || &&.
- Поведение перегруженных операций должно соответствовать поведению этих операций для стандартных типов данных: операция + не должна изменять своих аргументов, операция = должна возвращать ссылку на левый аргумент и т.п.
Формат перегрузки унарной операции @ как метода:
тип результата operator@
()
или
тип результата operator@
() const
Формат перегрузки унарной операции @ как функции:
тип результата operator@
(имя класса & )
или
тип результата operator@
(const имя класса & )
Исключение: В случае постфиксных
++ и
-- добавляется фиктивный параметр типа
int.
как метод:
имя класса operator@
(int)
как функция:
имя класса operator@
(имя класса & , int)
Формат перегрузки бинарной операции @ как метода:
тип результата operator@
(тип параметра2)
или
тип результата operator@
(тип параметра2) const
Левый аргумент операции передается как
*this и может быть только определяемого типа. Конструкторы-преобразователи к левому аргументу не применяются.
Формат перегрузки бинарной операции @ как функции:
тип результата operator@
(тип параметра1,тип параметра2)
где по крайней мере один из параметров должен относиться к определяемому типу. Если левый аргумент может иметь тип, отличный от определяемого, необходимо определять операцию как функцию.
Замечания:
- При перегрузке операции как функции, эту функцию нужно делать дружественной классу только в том случае, если для её эффективной реализации необходим доступ к закрытым элементам класса, иначе лучше определять обычную функцию (см. тему "Рекомендации по проектированию")
- Если операция присваивания не определяется программистом, компилятор создает её сам. В этом автоматически созданном методе вызываются операции присваивания для всех базовых классов и полей.
- В большинстве случаев нет необходимости определять операцию присваивания самостоятельно.
- Но если класс содержит указатели на динамически выделяемую память, то при присваивании произойдет дублирование идентичности этих значений. В результате изменение одного объекта приведёт к изменению другого объекта. Поэтому в случае использования указателей необходимо определять операцию присваивания самостоятельно.
- Если присваивание объектов не требуется, рекомендуется объявить операцию присваивания в разделе private, не определяя её реализацию (в С++11 рекомендуется писать =delete после заголовка).
- Кроме присваивания компилятор сам определяет операцию взятия адреса.