C++多态性之运算符重载

运算符重载为成员函数

当C++不存在某些现实中存在的运算(比如复数的加减)或不存在满足我们要求的运算符时,我们可以对运算符进行重载。
重载为成员函数的运算符函数定义形式为:

函数类型 operator 运算符(形参)
{
	...
}

此时参数即形参的个数=原操作数-1(后置++,–除外,因为这两个需要额外加一个int类型的形参来区分是前置或还是后置运算符)

以下两种情况运算符不能重载为成员函数:
1.当重载为成员函数的运算符时,左操作数一定是类的对象,不能为其他类型,比如重载实数+复数时,实数不是自定义的复数类,不能采用重载为类成员函数的形式。
2.当左操作数是类成员,但是这个类不是由自己定义的,比如是类库中的类,此时,不能直接在此类中增加成员函数对运算符进行重载。

注:存在必须重载为类成员函数的操作符:赋值(=),下标 ([ ]),调用(( )),成员访问(->)。 参考https://blog.csdn.net/qq_29344757/article/details/78820189

双目运算符重载

双目运算符重载规则:如果要重载运算符O为类成员函数,使之能够实现表达式 oprd1 O oprd2,其中oprd1为A类对象,那么运算符O应该重载为A类的成员函数,形参类型应该是oprd2所属类型。
经重载后,表达式oprd1 O oprd2就相当于oprd1.operator O(oprd2);
以下程序对复数的双目加减运算进行了重载,实现了复数的加减:

class Complex{
	public:
		Complex(double r=0.0,double i=0.0):real(r),imag(i){
		}
		Complex operator +(const Complex &c2) const{
			return Complex(real+c2.real,imag+c2.imag);
		}
		Complex operator -(const Complex &c2) const{
			return Complex(real-c2.real,imag-c2.imag);
		}
		void display(){
			cout<<"("<<real<<","<<imag<<")"<<endl;
		}
	private:
		double real;
		double imag;
}; 
int main(){
	Complex c1(5,2);Complex c2(2,10);Complex c3;
	c1.display();c2.display();
	c3=c1+c2;
	c3.display();
	c3=c1-c2;
	c3.display();
	return 0;
}

单目运算符重载

前置的单目运算符重载规则
如果要重载O为类成员函数,使之能够实现表达式 O oprd,其中oprd为A类对象,那么运算符O应该重载为A类的成员函数,形参类型应该为空。
经重载后,表达式O oprd就相当于oprd.operator O();
后置的单目运算符重载规则
与前置规则一致,只是必须具有一个int类型的形参。
经重载后,表达式oprd O就相当于oprd.operator O(int);
注:这个int类型的形参只是用来区分是前置还是后置运算符,无参数为前置,有参数为后置,且这个参数在函数体中不能够使用。

在以下代码中实现对时钟的读秒++运算:

class Clock{
	public: 
		Clock(int hour,int minute,int second){
			if(0<=hour&&hour<24&&0<=minute&&minute<60&&second>=0&&second<60){
				this->hour=hour;
				this->minute=minute;
				this->second=second;
			}
			else{
				cout<<"time is worry"<<endl;
			}
		}
		void showTime(){
			cout<<hour<<":"<<minute<<":"<<second<<endl;
		}
		Clock& operator ++(){ //前置++直接输出结果,不存在中间变量,返回一个引用能减小消耗
			second++;
			if(second>=60){
				second-=60;minute++;
				if(minute>=60){
					minute-=60;hour=(hour+1)%24;
				}
			}
			return *this;
		}
		Clock operator ++(int){//后置++需要返回一个局部变量(+1前的值),因此不能返回引用
			Clock old =*this;
			++(*this);
			return old;
		}
		private:
			int hour,minute,second;
}; 
int main(){
	Clock c(23,59,59);
	c.showTime();
	(c++).showTime();
	(++c).showTime();
	return 0;
}


从运行结果来看可知对++运算进行了重载,使之实现了时钟的+1。同时,也加深我们对i++和++i的理解,i++是对现有结果输出,同时+1;++i则是对现有结果+1之后再输出。

运算符重载为非成员函数

重载为非成员函数的运算符重载规则:
1.函数的形参列表表依次从左向右的的次序排列各操作数;
2参数的个数=原操作数个数(后置的++,–等除外,因为要加一个int类型的形参区分前置还是后置);
3.至少应该有一个自定义类型的操作数,不能两个操作数都是基本类型的,比如不能重载一个两个实数的加法,这是不允许的。
双目运算符经重载后,表达式oprd1 O oprd2就相当于operator O(oprd1,oprd2);
前置单目运算符重载后,表达式O oprd就相当于operator O(oprd);
后置单目运算符重载后,表达式oprd O就相当于operator O(oprd,0);
看以下例子完成对复数的加减重载为非成员函数:

class Complex{
	public:
		Complex(){
		}
		Complex(int a,int b):real(a),imag(b){
		}
		friend Complex operator +(const Complex &c1,const Complex &c2 );//声明为友元使得能够访问类的私有变量
		friend Complex operator -(const Complex &c1,const Complex &c2 );
		friend ostream & operator <<(ostream &out,const Complex &c );
		void show(){
			cout<<real<<","<<imag<<endl; 
		}
	private:
		int real;
		int imag;
};
Complex operator +(const Complex &c1,const Complex &c2 ){
	return Complex(c1.real+c2.real,c1.imag+c2.imag);
}
Complex operator -(const Complex &c1,const Complex &c2 ){
	return Complex(c1.real-c2.real,c1.imag-c2.imag);
}
ostream & operator <<(ostream &out,const Complex &c ){
	out<<"("<<c.real<<","<<c.imag<<")"; 
	return out;
}
int main(){
	Complex c(1,2);
	Complex d(2,3);
	Complex e;
	e=c+d;
	cout<<e<<endl;
	return 0;
}

上述程序中将运算符重载为非成员函数,并将其声明为复数类的友元,使得能在在类外访问类的私有成员,其实也可以通过类的共有接口去访问类的私有成员,但是声明为友元运算的效率会高一些。
同时对双目<<运算进行了重载,实现了直接输出复数的形式。注意在重载时,左操作数是std::ostream的引用,右操作数是复数类的常引用,返回std::ostream引用实现多级的输出。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值