Перегрузка операторов
Перегрузка операторов
С++ позволяет нам перегружать функции, т.е. мы можем объявлять несколько функций с одним именем в одной и той же области видимости, если они имеют различные списки параметров. Кроме того, С++ поддерживает перегрузку операторов, позволяя назначать специальную семантику встроенным операторам (таким, как +, << и [ ]) при их применении для пользовательских типов.
Мы уже видели несколько примеров с перегруженными операторами. Когда использовался оператор << для вывода текста в поток cout или cerr, мы не пользовались оператором С++, выполняющим поразрядный сдвиг влево, но использовали специальную версию этого оператора, принимающего слева объект потока ostream (например, cout или cerr), а справа — строку (либо вместо строки число или манипулятор потока, например endl) и возвращающего объект ostream, что позволяет несколько раз вызывать оператор в одной строке.
Красота перегрузки операторов заключается в возможности сделать поведение пользовательских типов в точности таким же, как поведение встроенных типов. Чтобы показать, как работает такая перегрузка, мы перегрузим операторы +=, —=, + и —, добавив возможность работы с объектами Point2D:
01 #ifndef POINT2D_H
02 #define POINT2D_H
03 class Point2D
04 {
05 public:
06 Point2D();
07 Point2D(double x, double у);
08 void setX(double x);
09 void setY(double у);
10 double x() const;
11 double y() const;
12 Point2D &operator+=(const Point2D &other)
13 {
14 xVal += other.xVal;
15 yVal += other.yVal;
16 return *this;
17 }
18 Point2D &operator-=(const Point2D &other)
19 {
20 xVal -= other.xVal;
21 yVal -= other.yVal;
22 return *this;
23 }
24 private:
25 double xVal;
26 double yVal;
27 };
28 inline Point2D operator+(const Point2D &a, const Point2D &b)
29 {
30 return Point2D(a.x() + b.x(), a.y() + b.y());
31 }
32 inline Point2D operator-(const Point2D &a, const Point2D &b)
33 {
34 return Point2D(a.x() - b.x(), a.y() - b.y());
35 }
36 #endif
Операторы можно реализовать либо как функции—члены, либо как глобальные функции. В нашем примере мы реализовали операторы += и —= как функции—члены, а операторы + и — как глобальные функции.
Операторы += и —= принимают ссылку на другой объект Point2D и увеличивают или уменьшают координаты x и у текущего объекта на значение координат другого объекта. Они возвращают *this, т.е. ссылку на текущий объект (this имеет тип Point2D *). Возвращение ссылки позволяет создавать экзотический программный код, например:
a += b += с;
Операторы + и — принимают два параметра и возвращают значение объекта Point2D (а не ссылку на существующий объект). Ключевое слово inline позволяет поместить эти функции в заголовочный файл. Если бы тело функции было более длинным, мы бы поместили в заголовочный файл прототип функции, а определение функции (без ключевого слова inline) в файл .cpp.
Следующие фрагменты программного кода показывают, как можно использовать все четыре перегруженных оператора:
Point2D beta(77.5, 50.0);
Point2D alpha(12.5, 40.0);
alpha += beta;
beta -= alpha;
Point2D gamma = alpha + beta;
Point2D delta = beta - alpha;
Кроме того, можно вызывать функции operator точно так же, как вызываются любые другие функции:
Point2D beta(77.5, 50.0);
Point2D alpha(12.5, 40.0);
alpha.operator+=(beta);
beta.operator-=(alpha);
Point2D gamma = operator+(alpha, beta);
Point2D delta = operator-(beta, alpha);
Перегрузка операторов в С++ представляет собой сложную тему, однако мы вполне можем пока обходиться без знания всех деталей. Все же важно понимать принципы перегрузки операторов, потому что несколько классов Qt (в том числе QString и QVector<T>) используют их для обеспечения простого и более естественного синтаксиса для таких операций, как конкатенация и добавление в конец объекта.