所谓的运算符重载是指对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。
例如:我们要将两个数组相加是一种很常见的现象,通常我们是用for循环来实现:
for(int i=0;i<20;i++)
a[i]=b[i]+c[i];
在C++中,可以定义一个表示数组的类,然后重载+运算符。使得:
a=b+c;
运算符函数的定义与其他函数的定义类似,惟一的区别是运算符函数的函数名是由关键字operator和其后要重载的运算符符号构成的。运算符函数定义的一般格式如下:
<返回类型说明符> operator <运算符符号>(<参数表>)
{
<函数体>
}
两个运算符重载的示例
运行结果为4。#include <iostream> using namespace std; class X { int i; public: X(int ii=0){i=ii;} X operator +(const X &rx) { i+=rx.i; return X(i); } int GetI(){return i;} }; int main() { X a(1),b(3); cout<<(a+b).GetI()<<endl; return 0; }
再举一个时间相加的例子:
程序运行结果为:#include <iostream> using namespace std; class Time { private: int hours; int minutes; public: Time(){hours=minutes=0;} Time(int h,int m=0) { hours=h; minutes=m; } Time operator+(const Time & t)const { Time sum; sum.minutes=minutes+t.minutes; sum.hours=hours+t.hours+sum.minutes/60; sum.minutes%=60; return sum; } void show() const { cout<<hours<<" hours,"<<minutes<<" minutes"; } }; int main() { Time planning; Time coding(2,40); Time fixing(5,55); Time total; cout<<"planning time="; planning.show(); cout<<endl; cout<<"coding time="; coding.show(); cout<<endl; cout<<"fixing time="; fixing.show(); cout<<endl; total=coding+fixing; cout<<"coding+fixing="; total.show(); cout<<endl; Time morefixing(3,28); cout<<"more fixing time="; morefixing.show(); cout<<endl; total=morefixing.operator+(total); cout<<"morefixing.operator+(total)="; total.show(); cout<<endl; return 0; }
![]()
分析一下这个函数,有两个构造函数,会根据所给数据的参数来选择用哪个构造函数,开始定义了一个没有参数的planing,所以选择的是默认构造函数,其中hours和minutes都设置为0,接着定义了2个有参数的
Time coding(2,40); Time fixing(5,55);
选择的是第二个构造函数,显示出来的,然后对于重载运算符也有两种使用方法,第一种就是把运算符重载当做函数调用使用:
total=morefixing.operator+(total);
另外一种方法就是运算符表示法:
total=coding+fixing;
基于友元函数的运算符重载的示例
根据前面缩写的知道,由于类的封装性质,类中的私有成员,在类外边的函数是无法访问的,然而为了某些编程需要,外边的函数要访问类里面的私有成员。C++提供了这种机制,就是友元函数。那为什么在运算符重载中需要友元函数。可以看下面在各分例子:
对上面时间Time类的乘法*运算符的重载可以通过定义一个类成员函数:Time operator *(double d)来实现。当表达式t=t1*2.5的时候,编译器就会调用t1.operator*(2.5)来完成运算。不过,如果表达式是t=2.5*t1呢?由于2.5在前面,并且并没有对2.5进行Time的类型转换函数的重载,所以无法进行表达式的计算。但是事实上,t1*2.5跟2.5*t1结果是没有区别的,如果实现这两种表达式的兼容呢?
一种方法是再实现一个全局函数来完成,当然了,它需要两个参数,一个是double,一个是Time,像这样Time operator * (double d,Time &t)。但是这个函数有一个问题是,作为非类成员函数,它无法访问类里面的私有成员数据,怎么办呢?友元出场!在函数的前面添加一个friend关键字,就可以搞掂。
下面是值得注意的几点:
1、参数为相同类型的二元运算符重载,事实上有两种方式,比如说Time的相加。一种是类成员函数Time operator+(&Time),另外一种就是使用友元函数:friend Time operator+(Time &t1,Time &t2)。可以选择二者之一,但不可以二者皆选,否则编译器会报错。
2、其实友元函数的实现可以使用非友元函数来实现,可以这样来实现一个全局函数:t=2.5*t1=operator*(2.5,t1);
<pre name="code" class="cpp">Time operator * (double d,const Time &t) { Time result; long totalminutes=t.hours*d*60+t.minutes*d; result.hours=totalminutes/60; result.minutes=totalminutes%60; return result; }
当运算符函数是一个成员函数时,最左边的操作数(或者只有最左边的操作数)必须是运算符类的一个类对象(或者是对该类对象的引用)。如果左边的操作数必须是一个不同类的对象,或者是一个内部类型的对象,该运算符函数必须作为一个友元函数来实现。
<strong> </strong>#include <iostream> using namespace std; class Complex{ public: Complex(double r=0.0,double i=0.0) { real=r; image=i; } friend Complex operator+(const Complex&,const Complex&); void display(); private: double real; double image; }; Complex operator+(const Complex &c1,const Complex &c2) { return Complex(c1.real+c2.real,c1.image+c2.image); } void Complex::display() { cout<<"("<<real<<","<<image<<"i)"<<endl; } int main() { Complex c1(3,4),c2(5,-10),c3; c3=c1+c2; cout<<"c1=";c1.display(); cout<<"c2=";c2.display(); cout<<"c1+c2=";c3.display(); return 0; }