Полиморфизм. Перегрузка операций
Отличительной особенностью С++ является способность перегрузки (переопределения) существующих операций. Встроенные операции, такие как +, являются изначально перегруженными даже в языке С.
Пример 18.
Перегрузка встроенной операции +.
void main ()
{ int i = 2, j = 3; k;
float a = 2.5, b = 1.3, c;
k = i + j;
c = a + b;
cout<< "k=" << k <<" c=" << c;
}
Результаты: k=5 c=3.8
Для операндов типа int и float используется одна и та же операция, но, очевидно, что код генерируется разный, так как целые и вещественные числа представляются в памяти по разному. С++ просто расширяет эту идею, давая возможность переопределять операции на уровне пользователя.
За небольшим исключением большинству операций языка С++ может быть придано специальное значение относительно вновь определенных классов. Для встроенных типов данных значение операции изменить нельзя. Например, класс, который определяет список указателей, может использовать операцию + для добавления объекта в список.
Когда операция перегружена, ни одно из ее исходных значений не теряется. Просто вводится новая операция относительно нового конкретного класса. Для этого создается специальная функция-операции, которая определяет действие этой операции согласно форме:
тип имя_класса :: operator # ( список аргументов)
{ // операторы, определяющие действие функции-операции
. . .
},
где тип – тип возвращаемого значения, # – конкретный знак операции.
Часто возвращаемое значение того же типа, что и класс, хотя возможен и другой тип этого значения. Функция-операции должна быть или элементом класса или дружественной функцией, при этом имеются небольшие отличия.
Пример 19.
Рассмотрим программу, в которой перегружаются операции: +, ++, --, = относительно класса Vector, который определяет трехмерный вектор в евклидовом пространстве с координатами x, y, z. Операция сложения двух векторов выполняется как сложение соответствующих координат.
#include<iostream.h>
#include<conio.h>
class Vector
{ int x, y, z; // координаты вектора
public:
Vector(int mx=0, int my=0, int mz=0); // конструктор с 3-мя параметрами
// по умолчанию
Vector operator + (Vector t); // функция-операция +
Vector operator = (Vector t); // функция-операция =
Vector operator ++ (); // функция-операция ++
Vector operator - - (); // функция-операция - -
void show(void); // функция вывода координат
};
Vector::Vector(int mx, int my, int mz) // конструктор с 3-мя параметрами
{ x=mx; y=my; z=mz; // инициализация 3-х координат
}
// Перегрузка операции +
Vector Vector::operator + (Vector t) // использование указателя this
{ Vector temp;
temp.x = x + t.x; // temp.x = this->x + t.x; и т. д.
temp.y = y + t.y;
temp.z = z + t.z;
return temp;
}
// Перегрузка операции =
Vector Vector::operator = (Vector t) // использование указателя this
{ x = t.x; // this->x = t.x; и т. д.
y = t.y;
z = t.z;
return *this; // возврат указателя this
}
// Перегрузка операции ++ (унарной префиксной и постфиксной одинаково)
Vector Vector::operator ++ ()
{
x++; y++; z++; // увеличение координат на 1
return *this; // возврат указателя this
}
// Перегрузка операции -- (унарной префиксной и постфиксной одинаково)
Vector Vector::operator -- ()
{
x--; y--; z--; // уменьшение координат на 1
return *this; // возврат указателя this
}
void Vector::show(void) // функция вывода 3-х координат
{
cout <<" x=" << x << " y=" << y << " z=" << z << '\n';
}
void main() // главная функция
{ clrscr(); // чистка экрана
Vector a(3, 2, 1), b(10, 20, 30), c; // три объекта с инициализацией
cout<<"вектор исходный а: "; a.show(); // вывод вектора а
cout<<"вектор исходный b: "; b.show(); // вывод вектора b
c=a + b; // перегруженный оператор +
cout<<"вектор c=a+b: "; c.show(); // вывод вектора с
c=a+b+c; // перегруженный оператор +
cout<<"вектор c=a+b+c: "; c.show(); // вывод вектора с
c = b = a; // перегруженный оператор =
cout<<"вектор c=b=a: "; c.show(); // вывод вектора с
++b; // перегруженный оператор ++
cout<<"вектор ++b: "; b.show(); // вывод вектора b
b- -; // перегруженный оператор --
cout<<"вектор b- -: "; b.show(); // вывод вектора b
getch();
}
Результаты программы:
вектор исходный а: x=3, y=2, z=1
вектор исходный b: x=10, y=20, z=30
вектор c=a+b: x=13, y=22, z=31
вектор c=a+b+c: x=26, y=44, z=62
вектор c=b=a: x=3, y=2, z=1
вектор ++b: x=4, y=3, z=3
вектор b- -: x=3, y=2, z=1
Комментарии к программе.
Как видно, функция-операции имеет только один параметр, когда сами функции определяют бинарные операции (+, =). Первый операнд использует this-указатель, а второй – передается как параметр функции.
Если используются методы, то не нужны параметры для унарных операций и требуется лишь один параметр для бинарных операций. Объект, активизирующий операцию, передается в функцию-операцию неявно через указатель this.
В этом примере важно то, что возвращаемое значение имеет тип vector, что позволяет использовать выражение вида a+b+c. Перегруженная операция + не изменяет значения своих операндов, а перегруженная операция = модифицирует операнд слева.