Перегрузка Операций
Программист может определять смысл операций при их применении к объектам определенного класса. Кроме арифметических, можно определять еще и логические операции, операции сравнения, вызова () и индексирования [], а также можно переопределять присваивание и инициализацию. Можно определить явное и неявное преобразование между определяемыми пользователем и основными типами.
Классы дают средство спецификации в C++ представления неэлементарных объектов вместе с множеством действий, которые могут над этими объектами выполняться. Иногда определение того, как действуют операции на объекты классов, позволяет программисту обеспечить более общепринятую и удобную запись для манипуляции объектами классов, чем та, которую можно достичь используя лишь основную функциональную запись. Например:
class complex { double re, im;public: complex(double r, double i) { re=r; im=i; } friend complex operator+(complex, complex); friend complex operator*(complex, complex);};complex operator+(complex a, complex b){ complex c; c.re=a.re+b.re; c.im=a.im+b.im; return c;}complex operator*(complex a, complex b){ complex c; c.re=a.re*b.re-a.im*b.im; c.im=a.re*b.im+a.im*b.re; return c;}определяет простую реализацию понятия комплексного числа, в которой число представляется парой чисел с плавающей точкой двойной точности, работа с которыми осуществляется посредством операций + и * (и только). Программист задает смысл операций + и * с помощью определения функций с именами operator+ и operator*. Если, например, даны b и c типа complex, то b+c означает (по определению) operator+(b,c). Теперь есть возможность приблизить общепринятую интерпретацию комплексных выражений. Например:
complex a = complex(1, 3.1);complex b = complex(1.2, 2);complex c = b;a = b+c;b = b+c*a;c = a*b+complex(1,2);Выполняются обычные правила приоритетов, поэтому второй оператор означает b=b+(c*a), а не b=(b+c)*a.
Можно описывать функции, определяющие значения следующих операций:
+ - * / % ^ & | ~ != < > += -= *= /= %= ^= &=|= << >> >>= <<= == != <= >= &&|| ++ -- [] () new deleteИзменить приоритеты перечисленных операций невозможно, как невозможно изменить и синтаксис выражений. Нельзя, например, определить унарную операцию % или бинарную !. Невозможно определить новые лексические символы операций. Имя функции операции есть ключевое слово operator (то есть, операция), за которым следует сама операция, например, operator<<. Функция операция описывается и может вызываться так же, как любая другая функция. Использование операции — это лишь сокращенная запись явного вызова функции операции. Например:
complex c = a + b; // сокращенная записьcomplex d = operator+(a,b); // явный вызовПри наличии предыдущего описания complex оба инициализатора являются синонимами.
Бинарная операция может быть определена или как функция член, получающая один параметр, или как функция друг, получающая два параметра. Таким образом, для любой бинарной операции @ aa@bb может интерпретироваться или как aa.operator@(bb), или как operator@(aa,bb). Если определены обе, то aa@bb является ошибкой. Унарная операция, префиксная или постфиксная, может быть определена или как функция член, не получающая параметров, или как функция друг, получающая один параметр. Таким образом, для любой унарной операции @ aa@ или @aa может интерпретироваться или как aa.operator@(), или как operator@(aa). Если определено и то, и другое, то и aa@ и @aa являются ошибками. Рассмотрим следующие примеры:
class X { // друзья friend X operator-(X); // унарный минус friend X operator-(X,X); // бинарный минус friend X operator-(); // ошибка: нет операндов friend X operator-(X,X,X); // ошибка: тернарная // члены (с неявным первым параметром: this) X* operator&(); // унарное & (взятие адреса) X operator&(X); // бинарное & (операция И) X operator&(X,X); // ошибка: тернарное};Когда операции ++ и -- перегружены, префиксное использование и постфиксное различить невозможно.
Дата добавления: 2016-07-27; просмотров: 1367;