一、重载一元运算符
首先,通过一个例子来了解一下运算符重载:
#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);
}
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] 来进行输入输出,变得更加方便简单。同时,通过两个程序的转化,我们也能看出为什么重载【】的时候要通过引用返回。