C++允许我们重载函数,这意味着可以在同一作用域内用同样的名字同时声明多个函数,而只需保证它们的参数列表不同就可以了。另外,C++支持运算符重载(operator overloading)。也就是说,当需要在自定义的类型内使用内置运算符(比如+,<<和[ ])时,就可以给它们分配特殊的语义。
我们已经看到了许多运算符重载的例子。当使用<<把文字输出到cout或者cerr时,我们并没有出发C++的左移运算符,而是将其作为运算符的一种特殊使用形式:左侧带一个ostream对象(比如cout和cerr),右侧带一个字符串(或者,也可以是一个数字或者是一个流控制器,比如endl),返回的是该ostream对象,而且也允许在一行中多次调用。
运算符重载的巧妙之处在于我们可以让自定义类型的行为表现得就像使用内置类型的 行为一样。为了说明运算符重载是如何工作的,我们将会在Point2D对象的基础上重载+=,-=,+ 和 - 运算符:
#ifndef POINT2D_H
#define POINT2D_H
class Point2D
{
public:
Point2D();
Point2D(double x, double y);
void setX(double x);
void setY(double y);
double x() const;
double y() const;
Point2D &operator +=(const Point2D &other)
{
xVal +=other.xVal();
yVal +=other.yVal();
return *this;
}
Point2D &operator -=(const Point2D &other)
{
xVal -=other.xVal();
yVal -=other.yVal();
return *this;
}
privarte:
double xVal;
double yVal;
};
inline Point2D operator+(const Point2D &a, const Point2D &b)
{
return Point2D(a.x() + b.x(), a.y() +b.y());
}
inline Point2D operator-(const Point2D &a, const Point2D &b)
{
return Point2D(a.x() - b.x(), a.y() - b.y());
}
}
#endif;
运算符可以被初始化为成员函数或者全局函数。在例子中,我们把 += 和 -= 实现为成员函数,把 + 和 - 实现为全局函数。
+= 和 -= 运算符带一个指向另一个Point2D对象的引用,并在其他对象的x坐标和y坐标基础上,对当前对象的x坐标和y坐标进行增或减运算。它们返回 this,该值表示一个指向当前对象(它的类型是Point2D) 的引用。利用返回的这个引用,就可以写出特殊形式的代码,比如:
a += b+= c;
+和-运算符带两个参数并且通过变量(不是一个指向现存对象的引用)返回一个Point2D对象。inline关键字允许我们把这些函数的定义放在头文件中。如果某个函数的函数体比较长,那么将会把该函数的原型放在头文件中,然后把该函数的定义(不带inline关键字)放在一个.cpp文件中。
下列代码片断给出了编程应用中4种运算符的重载方法:
Point2D alpha(12.5, 40.0);
Point2D beta(77.5, 50.0);
alpha += beta;
beta -= alpha;
Point2D gamma = alpha + beta;
Point2D delta = beta = alpha;
也可以像调用其他函数一样来调用运算符函数:
Point2D alpha(12.5, 40.0);
Point2D beta(77.5, 50.0);
alpha.operator +=(beta);
beta.operator -=(alpha);
Point2D gamma = operator+(alpha, beta);
Point2D delta = operator-(beta, alpha);
在C++中,运算符重载是一个复杂的话题,但是在不必详知所有细节的情况下我们仍旧可以使用C++。但了解运算符重载的基本原理还是非常重要的,因为有多个Qt的类(包括QString和QVector<T>就是利用这一特性来提供一种更为为简单和自然的语法的,比如字符串的连接和追加等操作。)