Читайте также: |
|
x = 0
y = 0 Введите координаты точки B
x = 6
y = 0 Координаты точки D x = 3 y = 0 Введите координаты точки C
x = 0
y = 6 Координаты точки O x = 2 y = 2 Расстояние между точками = 6
Несколько замечаний по поводу этого примера. При передаче аргумента в операторные функции здесь использована передача по ссылке. Это повышает эффективность работы программы, поскольку такой аргумент не копируется при передаче; в функцию фактически передается указатель на объект. Другой довод в пользу использования ссылки в качестве параметра – она позволяет избежать вызова деструктора для копии объекта, созданной при передаче объекта-параметра. Конечно, с таким же успехом можно было бы передавать в функцию сам объект, однако это менее эффективно. Хотя нет никаких требований к возвращаемому операторной функцией значению, здесь обе операторные функции возвращают объект, который имеет тип класса. Смысл этого состоит в том, что это позволяет использовать результат сложения двух объектов в сложном выражении. Например, становятся вполне допустимыми следующие выражения:
D = A + B + C;
С другой стороны, допустимы выражения вида:
~ (A + B);
Здесь при вызове перегруженного оператора ~ используется временный объект, возвращаемый оператором сложения.
Обратите внимание также на то обстоятельство, что в приведённых выше реализациях перегруженных операторов создаётся, инициализируется и возвращается временный объект, который уничтожается после завершения работы. Возврат ссылки на несуществующий объект приводит к ошибке.
Пример также демонстрирует возможность использования в качестве параметра операторной функции-члена перечислимого типа данных. Надо только не забывать, что этот параметр представляет правый операнд оператора.
Благодаря перегруженному оператору умножения Dot Dot:: operator * (double d), компилятор поймет, что означает инструкция:
D = A * 2;
Однако для него останется совершенно-непонятной инструкция
D = 2 * A;
Более того, нет никакого способа дать разумное определение этой инструкции, ограничиваясь средствами операторной функции-члена. Путь для решения такой задачи открывает использование дружественной операторной функции.
Если операторная функция бинарного оператора объявляется как глобальная, она должна быть объявлена в виде:
friend <FuncType> operator X (<Type1> <Par1>, <Type2> <Par2>);
По крайней мере, один из этих параметров должен иметь тип класса, для которого перегружается оператор.
Хотя нет никаких ограничений на тип возвращаемого значения бинарных операторов, большинство определяемых пользователем операторов возвращают либо тип класса, либо ссылку на тип класса.
Рассмотрим пример использования дружественной операторной функции для перегрузки оператора умножения класса Dot. Дружественной функции не передается скрытый указатель this. Поэтому в случае перегрузки бинарного оператора ей приходится передавать два аргумента, первый из которых соответствует левому операнду, а второй – правому.
Объектно-ориентированное программирование
Лекция 8 Перегрузка операторов 7
Файл Doth
class Dot // класс точки
{
• • •
public:
friend Dot operator * (double m, Dot & D); // перегрузка оператора умножения числа на точку
};
Файл Dotcpp include ”Doth”
// реализация перегруженного оператора умножения числа на точку
Dot operator * (double m, Dot & D) {
Dot T ("Г, D.x*m, D.y*m);
return T; }
Перегрузка операторов Х =
В C++ существует несколько операторов, которые выполняют некоторое действие и присваивание одновременно:
+= -= /= *= %= «=»= &= л= |=
Например,
hi t А = 5; // объявление и инициализация переменной А
А += 2; // увеличивает значение переменной А на два
Эти операторы трактуются компилятором как бинарные. Если операторные функции являются членами класса, то первый операнд является текущим, а второй - параметром. При выполнении указанных операторов состояние текущего объекта, как правило, изменяется.
В классе задач, для которых мы создаём класс Vec, требуется операция поворота вектора на заданный угол, для которой удобно определить операции сдвига и сдвига с присваиванием. Для поворота вектора против часовой стрелки (положительный угол поворота) определим сдвиг влево, по часовой стрелке - сдвиг вправо. Если угол поворота измеряется в градусах, то второй операнд задаётся целым числом, если в радианах - числом с плавающей точкой.
Следующий пример показывает, как определить операторы сдвига и сдвига с присваиванием для класса Vec.
Файл Vech
class Vec // класс вектора
{
• • •
public:
Vec operator «(double f); // перегрузка оператора сдвига влево с вещественным параметром
Vec operator «(int f); // перегрузка оператора сдвига влево с целым параметром
Vec& operator «= (int f); // перегрузка оператора сдвига влево с присваиванием
};
Файл Vech
include "Vech"
// возвращает вектор, повёрнутый на f радиан против часовой стрелки
Vec Vec:: operator «(double f)
{
Vec T ("T"); // объявляет временный объект
T.x = x*cos (f) - y*sin (f); // вычисляет проекции
T.y = x*sin (f) + y*cos (f); // повёрнутого вектора
return T; // возвращает временный объект
}
// возвращает вектор, повёрнутый на f градусов против часовой стрелки
Vec Vec:: operator «(int f)
{
Vec T ("T"); // объявляет временный объект
const double pi = 4 * atan (1); // объявляет и инициализирует константу ж
double F = f * pi / 180.0; // пересчитывает градусы в радианы
Объектно-ориентированное программирование
Лекция 8 Перегрузка операторов 8
T = *this << F; // вызывает операторную функцию Vec:: operator << (double)
return T; // возвращает временный объект
}
// поворачивает текущий вектор на f градусов против часовой стрелки
Vec& Vec:: operator <<= (int f)
{
Vec T ("T"); // объявляет временный вектор
T = *this << f; // вызывает операторную функцию Vec:: operator << (int)
*this = T; // передаёт повёрнутый временный вектор в текущий объект
return *this; // возвращает текущий объект
}
Дата добавления: 2015-11-26; просмотров: 116 | Нарушение авторских прав