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] 来进行输入输出,变得更加方便简单。同时,通过两个程序的转化,我们也能看出为什么重载【】的时候要通过引用返回。

posted @ 2011-09-08 22:44  csqlwy  阅读(3384)  评论(0编辑  收藏  举报