C++之操作符
具有函数重载特征
对于整数进行加、减、乘、除等各种操作,其操作形式并不是函数形式(add(a, b)),而是操作符a+b形式,
由此可知,C++其实把操作符也看成是与函数有同样性质的实体。
因此,可以对操作符进行函数那样的定义,之后就可以自由的使用该操作符了,
如下是一个对一个二维坐标系上的实数矢量Point类,设计矢量类的加法代码实现:
#include <iostream>
using namespace std;
class Point
{
int x, y;
public:
void set(int a, int b)
{
x = a;
y = b;
}
void print()const
{
cout << "(" << x << "," << y << ")" << endl;
}
friend Point operator+(const Point& a, const Point& b);
friend Point add(const Point& a, const Point& b);
};
Point operator+(const Point& a, const Point& b)
{
Point s;
s.set(a.x + b.x, a.y + b.y);
return s;
}
Point add(const Point& a, const Point& b)
{
Point s;
s.set(a.x + b.x, a.y + b.y);
return s;
}
int main()
{
Point a, b;
a.set(3, 2);
b.set(1, 5);
(a + b).print();
operator+(a, b).print();
add(a, b).print();
return 0;
}
代码中(a+b)的操作,实际上C++是调用了函数operator+(a, b),C++将a+b转译为对operator+(a+b)的调用。
如果不用操作符,a+b的功能也是可以实现的。那就是要调用add函数,从上述代码可以看出,add函数与+操作符的功能完全一致。因此,操作符并不是必需的。
在C++中,内部已经实现了多几个版本的+操作,例如整数+,浮点+等。因此,任何自定义的+操作符行为都是对C++原有+操作符的重载。同理,其他操作符的定义也是重载。
同时从上面的代码可以看出,operator+和add函数体重都要用Point对象进行私有数据访问,但是作为普通函数不能访问类的私有成员,因此在Point类中以friend关键字引导进行函数声明后,就可以访问类的私有数据了。
C++操作符的一些规定:
1)不能创建一些新的操作符,例如@, **等不能定义他们为C++操作符。
2)C++还规定双目操作符“::”,“.”,“.*”不能重载,同时三目操作符“? :”不能重载。
3)C++的操作符重载后,其优先级和结合性是不会改变的。
4)操作数个数不变。
5)操作符的重载只能针对自定义的类型。即在操作符定义的参数表中,至少有一个参数必须是自定义类型。
另外,操作符可以作为类中的成员,也就是类的成员函数,这样,就不需要用friend了,可以直接访问类中的成员了。对上述的程序进行了修改,将operator+作为类成员函数,重载操作<<代替print操作。以使Point对象可以直接进行流操作:
代码如下:
#include <iostream>
using namespace std;
class Point
{
int x, y;
public:
void set(int a, int b)
{
x = a;
y = b;
}
Point operator+(const Point& d)
{
Point s;
s.set(x + d.x, y + d.y);
return s;
}
friend ostream& operator<<(ostream& o, const Point& d);
};
inline ostream& operator<<(ostream& o, const Point& d)
{
return o << "(" << d.x << ", " << d.y <<")\n";
}
int main()
{
Point p1, p2;
p1.set(3, 5);
p2.set(3, 2);
cout << p1 + p2;
return 0;
}
从上述代码可以看出,成员操作符定义中只有一个参数,与普通操作符不同。因为成员函数总是与对象捆绑使用,被捆绑的对象就是被操作的第一参数,因此,单目成员操作符没有参数,双目成员操作符只有一个参数。因此代码中+操作符只有一个参数。
所以s+t的操作可以写成成员函数的调用方式,即s.operator + (t)。
此处<<操作的前置对象是流类型的cout,不是Point类型,所以不能把该<<操作设计成Point的成员,而只能设计成普通函数,因而,其参数表中就有两个参数,而且为了能访问Point私有数据,必须用关键字friend引导。