c++运算符重载
一、重载一元运算符
首先,通过一个例子来了解一下运算符重载:
#include<iostream> using namespace std; class Counter { private: unsigned int count; public: Counter():count(0) {} Counter(unsigned int i):count(i) {} //constructor,one arg unsigned int get_count() const { return count; } Counter operator ++ () //prefix { //++count; //Counter tem; //tem.count=count; //return tem; return Counter(++count); } Counter operator ++ (int) //postfix { //count++; //Counter tem; //tem.count=count; //return tem; return Counter(count++); } }; int main() { Counter c1,c2; cout<<"c1="<<c1.get_count()<<endl; cout<<"c2="<<c2.get_count()<<endl; ++c1; c2=++c1; cout<<"c1="<<c1.get_count()<<endl; cout<<"c2="<<c2.get_count()<<endl; c2=c1++; cout<<"c1="<<c1.get_count()<<endl; cout<<"c2="<<c2.get_count()<<endl; return 0; }
1.关键词operator
重载运算符的声明符的基本格式为 :counter operator ++ ()----【返回类型 关键字operator 运算符本身 ()】
我们知道编译器区别重载函数的唯一方法,是查看函数参数的数据类型和个数;同样的,辨别重载运算符的唯一方法,是看操作数的数据类型:如果为int等的基本类型,编译器调用内置的例程,如果操作数为类的变量,编译器就调用用户所写的operator。
2无名的临时对象(unnamed temporary object)
1)上面程序中被注释的代码:
//++count;
//Counter tem;
//tem.count=count;
//return tem;
完全可以用return Counter(++count) 代替。
这里注意几点:
① 上语句创建了一个counter类的对象,但是对象是没有名称的(他存在不长,因此不需要名字)。这个无名对象的初始值为参数(++count)所提供的值;
② 但是这里我们再仔细看一下:这难道不需要一个携带一个参数的构造函数吗?? 是的,它需要!!因此上面的one arg constructor是必须的( ⊙ o ⊙ )啊!
2)这句Counter operator ++ (int),我们注意到有个int:在这里int并不是真正的参数,也不代表整数,int只是c++设计者选择用来表示后缀的标志!~
二、重载二元运算符
1)以算术运算符举例:
如:
Distance Distance::operator+(Distance dd) const { int f=feet+dd.feet; float i=inches+dd.inches; if (i>=12) { i-=12; f++; } return Distance(f,i); }
1)如d3=d1+d2表示:运算符左侧的d1为运算符所属的对象(程序中的feet和inches),而运算符右侧的d2为上面程序的参数dd;
2)由于有Distance(f,i)则类中必须要两个参数的构造函数才行。
3)enum{MAX=80};===static const int MAX=80
2)再看个例子(算术复制运算符):
#include <iostream> #include <conio.h> using namespace std; class Distance { private: int feet; float inches; public: Distance():feet(0),inches(0.0) {} Distance(int ft,float in):feet(ft),inches(in) {} void getdist() { cout<<"Enter feet:"; cin>>feet; cout<<"Enter inches:"; cin>>inches; } void showdist(int i) { cout<<i<<":The feet:"<<feet<<endl; cout<<i<<":The inches:"<<inches<<endl; } void operator += (Distance) ; }; void Distance::operator+=(Distance dd) { feet+=dd.feet; inches+=dd.inches; if (inches>=12.0) { inches-=12.0; feet++; } } int main() { Distance d1,d3; Distance d2(7,9.5); d1.getdist(); d1+=d2; //正确 d3 = d1 += d2; //错误!!! d1.showdist(1); d2.showdist(2); d3.showdist(3); getch(); return 0; }
上例中:重载+=运算符没有返回值,所以只能单独使用,即:d1+=d2;
如果希望诸如 d3 = d1 += d2;这样的表达式,那么就是错误的,因为他缺少一个返回值。
3.下标运算符【】
重载的下标运算符只有通过引用返回才会有用:因为这个运算符通常在等号左方使用,所以重载函数不得不通过引用返回。
这里通过一个安全数组的例子来说明:
首先(不用重载):
#include <iostream> using namespace std; const int LIMIT=100; class safearay { private: int arr[LIMIT]; public: int& access(int n) { if (n<0||n>=LIMIT) { cout<<"Index out of bounds"; exit(1); } return arr[n]; } }; int main() { safearay s1; for (int j=0;j<LIMIT;j++) { s1.access(j)=j*10; } for (int j=0;j<LIMIT;j++) { int temp=s1.access(j); cout<<"Element "<<j<<" is "<<temp<<endl; } return 0; }
在这个程序中s1.access(j)=j*10; 这句等号的左边要使用函数调用,因此调用的函数必须通过引用返回。(还用一个通过引用返回的例子是避免虚函数中见到的巨大的对象)。
如果把上面的程序进一步简化,从而使用下标重载:
#include <iostream> using namespace std; const int LIMIT=100; class safearay { private: int arr[LIMIT]; public: int& operator [] (int n) { if (n<0||n>=LIMIT) { cout<<"Index out of bounds"; exit(1); } return arr[n]; } }; int main() { safearay s1; for (int j=0;j<LIMIT;j++) { s1[j]=j*10; } for (int j=0;j<LIMIT;j++) { int temp=s1[j]; cout<<"Element "<<j<<" is "<<temp<<endl; } return 0; }
可以看出程序中使用: s1[j]=j*10 以及 int temp=s1[j] 来进行输入输出,变得更加方便简单。同时,通过两个程序的转化,我们也能看出为什么重载【】的时候要通过引用返回。