Перегрузка операций

Часто, для удобства, бывает полезно переопределить некоторый оператор для класса (например, + для векторов). Тогда запись программы становится более компактной и понятной. Общая форма определения оператора выглядит следующим образом:

<return_type> operator <operator_sign> (<operator_parametres>);

Операторы бывают унарные (работающие с одним объектом) и бинарные (работающие с двумя объектами). Примеры унарных операторов: ++, --, * (оператор разыменования). Примеры бинарных операторов: +, +=, * (умножение), ==.

Операторы являются теми же функциями, только со специальными именами. Они могут быть объявлены как вне класса, так и как член класса. Пример перегрузки операторов:

int_pair.cpp
class int_pair{
    int first, second;
public:
    int_pair(int f = 0, int s = 0): first(f), second(s) {}
    bool operator == (const int_pair& p) const {
        return (first == p.first) && (second == p.second);
    }
};

bool operator != (const int_pair& p1, const int_pair& p2){
    return !(p1 == p2);
}

Обычно унарные операторы объявляются как часть класса. Бинарные операторы могут быть объявлены как внутри класса, так и вне класса. Бинарный оператор, объявленный внутри класса, имеет только один входной параметр (вторым параметром оператора будет объект, оператор которого вызывается). Бинарные операторы, объявленные вне класса, имеют два параметра.

Рекомендация: для определения, где лучше всего описывать оператор - внутри класса или вне его, - спросите себя, изменяет ли этот оператор свои входные параметры. Если изменяет - то этот оператор - часть класса. Если не изменяет, то оператор лучше всего определить вне класса.

В следующем примере показаны способы перегрузки операторов для двумерного вектора:

vector.cpp
class vector{
    float x, y;
public:
    vector(float p1 = 0, float p2 = 0): x(p1), y(p2) {}
    vector operator = (const vector& p){
        x = p.x;
        y = p.y;
        return *this;
    }
    void operator += (const vector& p){
        x += p.x;
        y += p.y;
    }
};

vector operator + (const vector& p1, const vector& p2){
    vector tmp;
    tmp = p1;
    tmp += p2;
    return tmp;
}

Обычно бинарные операторы, определенные в классе, объявляют возвращающими значение. С моей точки зрения эта практика неудобна, потому что код, написанный с использованием данных операторов трудночитаем. Например, попробуйте оценить результат выполнения кода:

headshot.cpp
 int a = 4,
     b = 2,
     c = 1;
 c = a += (c += a = b) *= (a /= b) = a;

Last updated