c++操作符重载(翻译)
翻译自:http://www.cplusplus.com/doc/tutorial%20%20/classes2/
对于c++中基本的类型,我们可以采用如下方式进行操作:
int a, b, c;
a = b + c;
但是,对下面的操作就会产生编译错误,因为我们没有定义这个操作类型有“+”操作。
struct {
string product;
float price;
} a, b, c;
a = b + c;
但是,幸好有c++的操作符重载,我们可以设计实现上例中的操作。
下面是能够重载的操作符列表:
可重载的操作符 |
+ - * / = < > += -= *= /= << >> <<= >>= == != <= >= ++ -- % & ^ ! | ~ &= ^= |= && || %= [] () , ->* -> new delete new[] delete[] |
我们在类中使用操作函数去重载一个操作符,这个函数是一个以operator关键字后加需要重载的操作符(sign)为函数名称的普通函数,格式如下:
typeoperator sign (parameters){/*…*/}
下面是一个重载“+”操作符的例子,这个例子是创建一个存储双向vectors向量类,然后我们使用重载的“+”操作符直接相加两个类的对象a(3,1)和b(1,2)。两个向量相加的操作如下,两个x坐标相加获得x坐标结果,两个y坐标相加获得y坐标结果,因此最后结果为:(3+1,1+2) = (4,3)。
// vectors: overloading operators example
#include <iostream>
using namespace std;
class CVector {
public:
int x,y;
CVector () {};
CVector (int,int);
CVector operator + (CVector);
};
CVector::CVector (int a, int b) {
x =a;
y =b;
}
CVector CVector::operator+ (CVector param){
CVector temp;
temp.x = x + param.x;
temp.y = y + param.y;
return (temp);
}
int main () {
CVector a (3,1);
CVector b (1,2);
CVector c;
c =a + b;
cout << c.x << "," << c.y;
return 0;
}
程序中的以下两句可能会让你感到迷惑:
CVector (int, int); // function name CVector(constructor)
CVector operator+ (CVector); // function returns a Cvecto
上边的是CVector类的构造函数,带两个int类型的参数,下面的是返回为Cvector类型的“+”操作符函数。
Cvector类的operator+函数是重载“+”操作符的一种方式。这个函数即可以用“+”操作符隐式调用也可以用函数名显示调用,如下两种方式:
c = a + b;
c = a.operator+(b);
这两种调用方式是等价的。
我们会发现类中有个空的结构体(没有参数),并且用空的模块定义:CVector () { };
这是必须要的,虽然我们显示的调用另一个结构体:CVector (int, int);
如果没有空的结构体,main中的CVector c;就会变的不合法。
无论如何,我还是要警告你,一个空的模块对于一个构造函数是不好的,因为它没有满足结构体最小的功能---初始化类中所有的成员变量。在上边的例子中,结构体中并没有初始化变量x和y。因此,更好的定义如下:
CVector () { x=0; y=0; };
同时,类中包含一个默认的拷贝构造函数(即使它们没定义),同时也包括一个默认的以类作为参数的“=”操作符函数。例子如下:
CVector d (2,3);
CVector e;
e = d; // copy assignment operator
这个拷贝操作符函数唯一的默认的操作符函数,当然你可以重新定义其他的功能,例如拷贝某些类的成员或者增加初始化操作等。
重载操作符不要改变操作符的原有的数学或者通用的操作规则,例如不要重载operator+操作符来实现“-”的操作。
函数operator+的原型是很明显的,右操作符作为操作符成员函数的参数,其他的操作符可能就没那么明显了。下表是不同操作符函数声明一个总结:
表达式 |
操作符 |
成员函数 |
全局函数(友元函数) |
@a |
+ - * & ! ~ ++ -- |
A::operator@() |
operator@(A) |
a@ |
++ -- |
A::operator@(int) |
operator@(A,int) |
a@b |
+ - * / % ^ & | < > == != <= >= << >> && || , |
A::operator@ (B) |
operator@(A,B) |
a@b |
= += -= *= /= %= ^= &= |= <<= >>= [] |
A::operator@ (B) |
- |
a(b, ...) |
() |
A::operator() (B, C...) |
- |
a->x |
-> |
A::operator->() |
- |
表中,a是类A的对象,b是类B的对象,c是类C的对象。
在表中,可以看出有两种方法可以重载一些类操作符:作为成员函数和最为全局函数。它们使用哪个的好处是不清楚的(视使用情景而定),但是提醒你的是,不是成员函数的函数----全局函数。如果是友元函数,可以访问此类的私有成员和保护成员。