-
Notifications
You must be signed in to change notification settings - Fork 6
Перегрузка операторов
При задаче «нового» оператора необходимо учесть несколько аспектов.
- Приоритет (* раньше +);
- арность (со сколькими операндами работаем);
- порядок выполнения (слеванаправо или справаналево).
В цыплюсе – новые операторы задаются только на множестве тех что уже есть, без добавления новых.
Запрещены к перегрузке: . :: . (вызов метода через указатель в СИ) ?: (тернарный).*
[тип] operator<знак> ([список параметров]) //longint operator * (longint &a, longint &b)
⚫️ Операторы можно перегружать как члены или как внешные функции (дружественные или нет). ⚫️ Оператор нью перегружается как статический метод класса (он вызывается чтобы создать объект – когда самого объекта нет).
Существует три формы его перегрузки.
//объявляется методом класса
void* operator new(size_t Size[, void *buff]); //модификатор статик можно написать, но здесь он используется автоматически
void* operator new[](size_t C); //нью служит ТОЛЬКО для выделения памяти; после возвращения области начинает работать конструктор
//delete возвращает void а не указатель
A* obj = new A;
Вернёмся к бинарным операторам + - * /
. Принято: если бинарный оператор изменяет существующие объекты, перегружать его надо как член класса, к примеру A+B == A += B.
Complex operator +(const Complex& C1, const Complex& C2)
{
return complex(C1.rl+C2.rl, C1.im+C2.im);
}
Оператор при этом должен быть другом класса.
Присваивание перегружается как член класса; выполняется справа налево. Перегрузка присваивания не влияет на инициализацию.
() перегружаются как оператор-член класса, НЕ статический. Получит как минимум один параметр – this, адрес объекта для которого был вызван. () нельзя перегружать для одного класса несколько раз – только единожды.
[] индексация. Позволяет создавать ассоциативные массивы. После перегрузки теряется транзитивность – вызываться будет всегда для левого объекта.
// ->
class A
{
public:
void f();
};
class B
{
public:
A* operator->();
};
B obj;
obj->f(); //(obj.operator->())->f()
Так называемый «умный указатель» - можно создавать объекты, выполняющие чисто транзитные операции. Через них вызываются методы нужного объекта. Позволяет работать со всеми объектами класса А, включая и производные, и даже если А абстрактный (virtual void f()=0;
)
++ -- инкремент и декремент. Постфиксный вариант выполняется после того, как объект отработал в выражении; учесть это никак нельзя.
class A
{
public:
A& operator++(); //++a
A& operator++(int); //a++0
operator int(); //оператор неявного приведения типа
}