Учись программированию на C++ Builder бесплатно!

Все операции С++ могут быть перегружены, кроме операций точка (.), разыменование (*), разрешение области действия (::), условная (?:) и sizeof.

Операции =, [], () и -> могут быть перегружены только как не статические функции-элементы. Они не могут быть перегружены для перечислимых типов. Все остальные операции можно перегружать, чтобы применять их к каким-то новым типам объектов, вводимым пользователем. Кроме того, многие операции уже перегружены в С++. Например, арифметические операции применяются к разным типам данных целым числам, действительным и т.д., именно в результате того, что они перегружены.

Операции перегружаются путем составления описания функции (с заголовком и телом), как это делается для любых функций, за исключением того, что в этом случае имя функции состоит из ключевого слова operator, после которого записывается перегружаемая операция. Например, имя функции operator+ можно использовать для перегрузки операции сложения. Чтобы использовать операцию над объектами классов, эта операция должна быть перегружена, но есть два исключения. Операция присваивания (=) может быть использована с каждым классом без явной перегрузки. По умолчанию операция присваивания сводится к побитовому копированию данных-элементов класса. Такое побитовое копирование опасно для классов с элементами, которые указывают на динамически выделенные области памяти, т.е. для таких классов следует явно перегружать операцию присваивания. Операция адресации (&) также может быть использована с объектами любых классов без перегрузки, т.е. она просто возвращает адрес объекта в памяти. Но операцию адресации можно также и перегружать.

Перегрузка не может изменять старшинство и ассоциативность операций. Нельзя также изменить число операндов операции. Например, унарную операцию можно перегрузить только как унарную. Перегрузка больше всего подходит для математических классов. Они часто требуют перегрузки значительного набора операций, чтобы обеспечить согласованность со способами обработки этих математических классов в реальной жизни. Например, было бы странно перегружать только сложение класса комплексных чисел, потому что обычно с комплексными числами используются и другие арифметические операции.

Цель перегрузки операций состоит в том, чтобы обеспечить такие же краткие выражения для типов, определенных пользователем, какие С++ обеспечивает с помощью богатого набора операций для встроенных типов. Однако перегрузка операций не выполняется автоматически, чтобы выполнить требуемые операции, программист должен написать функции, осуществляющие перегрузки операций.

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

Ниже приведен упрощенный пример создания класса комплексных чисел Complex, в котором переопределены операции сложения, вычитания и присваивания. Дается описание не всех функций, поскольку очевидно, что сложение и вычитание операции идентичные с точностью до знака.

class Complex {

public:

double Re; // действительная часть

double Im; // мнимая часть

Complex(double = 0.0, double = 0.0); // конструктор операции сложения

Complex operator+(const Complex &) const; // бинарная

Complex operator+() const; // унарная операции вычитания

Complex operator-(const Complex S) const; // бинарная

Complex operator-() const; // унарная

Complex &operator=(const Complex &); // присваивание

};

// Конструктор

Complex::Complex (double R, double I)

{

Re = R;

Im = I;

}

// Перегруженная бинарная операция сложения

Complex Complex::operator+(const Complex &X) const

{

Complex R;

R.Re = Re + X.Re;

R.Im = Im + X.Im;

return R;

}

// Перегруженная унарная операция вычитания

Complex Complex::operator-() const

{

Complex R;

R.Re = -Re;

R.Im = -Im;

return R;

}

// Перегруженная операция присваивания

Complex & Complex::operator=(const Complex &R)

{

Re = R.Re;

Im = R. Im;

return *this; // возможность сцепления

}

В этом классе вводится два открытых данных-элемента:

  • Re - действительная часть комплексного числа.
  • Im - мнимая часть.

Конструктор по умолчанию задает действительную и мнимую части равными 0.

Оператор:

Complex operator+(const Complex &) const;

объявляет прототип бинарной операции сложения. На то, что это операция бинарная, указывает наличие параметра правого операнда. Когда компилятор встретит в тексте операцию А + В, примененную к переменным типа Complex, он, незримо для пользователя, заменит ее выражением A.operator+(B).

Оператор:

Complex operator+() const;

объявляет прототип унарной операции сложения, поскольку список параметров пуст.

Прототипы операций вычитания и присваивания строятся аналогично.

В реализации функции бинарного сложения создается локальная переменная R типа Complex, в которой формируется возвращаемое значение. В процессе формирования к данным левого операнда производится обращение просто по именам Re и Im, а второй операнд является параметром, передаваемым в функцию по ссылке. В заключение значение сформированной переменной возвращается как результат функции.

В функции операции присваивания просто данные параметра пересылаются в поля Re и Im. Обратите внимание на последнюю строку, которая возвращает *this. Указатель this является указателем на объект данного класса. Подобный возврат ссылки необходим, чтобы можно было использовать сцепленные операции присваивания.

Если компилятор встречает в тексте выражение А = В, примененное к переменным типа Complex, он заменяет его выражением A.operator=(B). А что произойдет, если встретится выражение А = В = С? Поскольку ассоциативность операции присваивания справа налево, то сначала заменится вторая часть выражения на В.operator=(C). После замены первого знака равенства получится выражение А.operator=(B.operator=(С)). Для того чтобы это работало, нужно, чтобы выражение возвращало ссылку на объект В. Это и делается, возвращением в функции ссылки *this. Тогда обеспечивается правильное выполнение сцепленных присваиваний.

С описанным классом можно, например, выполнять такие действия:

Complex А(1,1), B(2,2), C, D;

А = -А;

С = А + В + В;

D = А - В;

А = B - С;

Поделиться