C++学习笔记——03 对运算符进行重载


🌿前言:本系列笔记是主要是对于谭浩强的c++程序设计的学习笔记再加上一些我自己的理解。如果有误欢迎大家指出。

建议是有基础的同学快速入门,或者复习用

一、为什么要对运算符重载

#include<iostream>
using namespace std;
class Complex
{
	public:
		Complex(){real=0;imag=0;}
		Complex(double r,double i){real=r;imag=i;}
		Complex complex_add(Complex &c2);
		void display();
	private:
		double real;
		double imag;
};
Complex Complex::complex_add(Complex &c2)
{
	Complex c;
	c.real=real+c2.real;
	c.imag=imag+c2.imag;
	return c;
}
void Complex::display()
{
	cout<<"("<<real<<","<<imag<<"i)"<<endl;
}
int main()
{
	Complex c1(3,4),c2(5,-10),c3;
	c3=c1.complex_add(c2);
	cout<<"c1=";c1.display();
	cout<<"c2=";c2.display();
	cout<<"c1+c2=";c3.display();
    return 0;
}

二、对运算符重载的方法

运算符重载的方法是定义一个重载运算符的函数,其实质上就是函数重载。

重载运算符的函数的一般格式:

函数类型 operator 运算符名称(形参表)

{对运算符的重载处理}

#include<iostream>
using namespace std;
class Complex
{
	public:
		Complex(){real=0;imag=0;}
		Complex(double r,double i){real=r;imag=i;}
		Complex operator+(Complex &c2);
		void display();
	private:
		double real;
		double imag;
};
Complex Complex::operator+(Complex &c2)
{
	Complex c;
	c.real=real+c2.real;
	c.imag=imag+c2.imag;
	return c;
}
void Complex::display()
{
	cout<<"("<<real<<","<<imag<<"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;
}

三、重载运算符的规则

1.用户只能对已有的C++运算符进行重载

2.C++允许重载的运算符

类型符号
双目算术运算符+(加)、–(减)、*(乘)、/(除)、%(取模)、
关系运算符==、!=、<、>、<=、>=
逻辑运算符||(逻辑或)、&&(逻辑与)、!(逻辑非)
单目运算符+(正)、–(负)、*(指针)、&(取地址)
自增自减运算符++、– –、
位运算符|(按位或)、&(按位与)、~(按位取反)、^(按位异或)、<<(左移)、>>(右移)
赋值运算符=、+=、–=、*=、/=、%=、&=、|=、^=、<<=、>>=、
空间申请与释放new、delete、new[]、delete[]、
其他运算符()(函数调用)、–>(成员访问)、–>*(成员指针访问)、,(逗号)、[] (下标)

不允许重载的运算符:

. (成员访问运算符)、*(成员指针访问运算符)、::(域运算符)、sizeof(长度运算符)、?: (条件运算符)、

3.重载不能改变运算符运算对象的个数

4.重载不能改变运算符的优先级

5.重载不能改变运算符的结合性

6.重载运算符的函数不能有默认参数

7.重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少有一个是类对象或其引用

8.用于类对象的运算符都必须重载,但“=”和“&”(取地址)是例外

四、运算符重载函数作为类成员函数和友元函数

对于运算符重载函数有两种处理方式一个是作为类成员函数,另一个是作为友元函数。

#include<iostream>
using namespace std;
class Complex
{
	public:
		Complex(){real=0;imag=0;}
		Complex(double r,double i){real=r;imag=i;}
        //Complex operator+(Complex &c2);
		friend Complex operator+(Complex &c1,Complex &c2);
		void display();
	private:
		double real;
		double imag;
};
Complex operator+(Complex &c1,Complex &c2)
{
	return Complex(c1.real+c2.real,c1.imag+c2.imag);
}
/*Complex Complex::operator+(Complex &c2)
{
	Complex c;
	c.real=real+c2.real;
	c.imag=imag+c2.imag;
	return c;
}*/
void Complex::display()
{
	cout<<"("<<real<<","<<imag<<"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;
}

如果将运算符重载函数作为成员函数,则可以少写一个函数参数。但要求运算符表达式中的第一个参数是一个类对象,并且与运算符函数的类型相同。如果运算符左侧的操作数是C++标准类型(如int)或是一个其他类的对象,则运算符重载函数不能作为成员函数,只能作为非成员函数。如果函数需要访问私有成员,可以声明为友元函数。

双目运算符重载为友元函数时则不能省略一个函数参数,并且在运算符表达式中,要求运算符左侧的操作数与函数第一个参数对应,右侧和第二个对应。

C++规定,赋值运算符=、下标运算符[]、函数调用运算符()、成员运算符–>必须作为成员函数。流插入<<和流提取运算符>>、类型转换运算符不能定义为成员函数,只能作为友元函数。一般将单目和复合运算符定义为成员函数,双目运算符为友元函数。

五、重载双目运算符

#include<iostream>
using namespace std;
class String
{
	public:
		String(){p=NULL;}
		String(char *str);
		void display();
	private:
		char *p;
};
String::String(char *str)
{
	p=str;
}
void String::display()
{
	cout<<p;
}
int main()
{
	String string1("Hello"),string2("Book");
	string1.display();
	cout<<endl;
	string2.display();
	return 0;
}
#include<iostream>
#include<string.h>
using namespace std;
class String
{
	public:
		String(){p=NULL;}
		String(char *str);
		friend bool operator>(String &string1,String &string2);
		void display();
	private:
		char *p;
};
String::String(char *str)
{
	p=str;
}
void String::display()
{
	cout<<p;
}
bool operator>(String &string1,String &string2)
{
	if(strcmp(string1.p,string2.p)>0)
	return true;
	else
	return false;
}
int main()
{
	String string1("Hello"),string2("Book");
	cout<<(string1>string2)<<endl;
}
#include<iostream>
#include<string.h>
using namespace std;
class String
{
	public:
		String(){p=NULL;}
		String(char *str);
		friend bool operator>(String &string1,String &string2);
		friend bool operator<(String &string1,String &string2);
		friend bool operator==(String &string1,String &string2);
		void display();
	private:
		char *p;
};
String::String(char *str)
{
	p=str;
}
void String::display()
{
	cout<<p;
}
bool operator>(String &string1,String &string2)
{
	if(strcmp(string1.p,string2.p)>0)
	return true;
	else
	return false;
}
bool operator<(String &string1,String &string2)
{
	if(strcmp(string1.p,string2.p)<0)
	return true;
	else
	return false;
}
bool operator==(String &string1,String &string2)
{
	if(strcmp(string1.p,string2.p)==0)
	return true;
	else
	return false;
}
void compare(String &string1,String &string2)
{
	if(operator>(string1,string2)==1)
	{
		string1.display();
		cout<<">";
		string2.display();
		cout<<endl;
	}
	else
	{
		if(operator<(string1,string2)==1)
		{
			string1.display();
			cout<<"<";
			string2.display();
			cout<<endl;
		}
		else
	    if(operator==(string1,string2)==1)
		{
			string1.display();
			cout<<"=";
			string2.display();
			cout<<endl;
		}
		
	}
}
int main()
{
	String string1("Hello"),string2("Book"),string3("Computer"),string4("Hello");
	compare(string1,string2);
	compare(string2,string3);
	compare(string1,string4);
	return 0;
}

六、重载单目运算符

#include<iostream>
using namespace std;
class Time
{
	public:
		Time(){minute=0;sec=0;}
		Time(int m,int s):minute(m),sec(s){}
		Time operator++();
		Time operator++(int)
;		void display(){cout<<minute<<":"<<sec<<endl;}
	private:
		int minute;
		int sec;		
};
Time Time::operator++()
{
	if(++sec>=60)
	{
		sec-=60;
		++minute;
	}
	return *this;
}
Time Time::operator++(int)
{
	Time temp(*this);
	sec++;
	if(sec>=60)
	{
		sec-=60;
		++minute;
	}
	return temp;
} 
int main()
{
	Time time1(34,59),time2;
	cout<<"time1 : " ;
	time1.display();
	++time1;
	cout<<"++time1 : ";
	time1.display();
	time2=time1++;
	cout<<"time1++ : ";
	time1.display();
	cout<<"time2 : ";
	time2.display();
	
}

七、重载流插入运算符和流提取运算符

用户自己定义的类型的数据(如类对象),是不能直接用“<<‘和”>>“输入和输出的,如果想用它们输出和输入自己声明的类型的数据,必须对它们重载。

重载的函数形式如下:

istream & operator>>(istream&,自定义类&);

ostream & operator<<(ostream&,自定义类&);

只能将重载“<<‘和”>>“的函数作为友元函数而不能定义为成员函数

1.重载流插入符“<<”
#include<iostream>
using namespace std;
class Complex
{
	public:
		Complex(){real=0;imag=0;}
		Complex(double r,double i){real=r;imag=i;}
		Complex operator+(Complex &c2);
		friend ostream& operator<<(ostream&,Complex&);
	private:
		double real;
		double imag;
};
Complex Complex::operator+(Complex &c2)
{
	return Complex(real+c2.real,imag+c2.imag);
}
ostream & operator<<(ostream & output,Complex& c)
{
	output<<"("<<c.real<<"+"<<c.imag<<"i)"<<endl;
	return output;//能连续向输出流插入信息
}
int main()
{
	Complex c1(2,4),c2(6,10),c3;
	c3=c1+c2;
	cout<<c3;
    return 0;
}

C++规定运算符“<<”重载函数的第一个参数和函数的类型都必须是ostream类型的引用,是为了返回cout的当前值以便连续输出。

2.重载流提取符“>>”
#include<iostream>
using namespace std;
class Complex
{
	public:
	    friend ostream& operator<<(ostream&,Complex&);
		friend istream& operator>>(istream&,Complex&);
	private:
		double real;
		double imag;
};
ostream & operator<<(ostream & output,Complex& c)
{
	output<<"("<<c.real;
	if(c.imag>=0)output<<"+";
	output<<c.imag<<"i)"<<endl;
	return output;
}
istream & operator>>(istream & input,Complex& c)
{
	cout<<"input real part and imaginary part of complex number:";
	input>>c.real>>c.imag;
	return input;
}
int main()
{
	Complex c1,c2;
	cin>>c1>>c2;
	cout<<"c1="<<c1;
	cout<<"c2="<<c2<<endl;
    return 0;
}

八、不同类型数据间的转换

1.标准类型数据间的转换
  • 隐式类型转换:系统自动完成的

    显式类型转换:在程序中指定将一种指定的数据转换成另一种指定的类型。

  • 显式类型转换的方法:

    C++:类型名(数据)

    C语言:(类型名)数据

2.把其他类型转换为类对象——用转换构造函数

转换构造函数只有一个形参,定义方法如下:

Complex(double r){real=r;imag=0;}

然后就可以在类的作用域中用以下方式进行转换:

类名(指定类型的数据)

Complex(double r)
3.将类对象转换为其他类型数据——用类型转换函数

类型转换函数的一般形式:

operator 类型名 ()

{实现转换的语句}

在函数名前不能指定函数类型,函数没有参数。且其只能作为成员函数,不能是友元函数或普通函数,因为转换的主体是本类的对象。

#include<iostream>
using namespace std;
class Complex
{
	public:
		Complex(){real=0;imag=0;}
		Complex(double r,double i){real=r;imag=i;}
		operator double(){return real;}
	private:
		double real;
		double imag;
};
int main()
{
	Complex c1(3,4),c2(5,-10),c3;
	double d;
	d=2.5+c1;
	cout<<d<<endl;
	return 0;
}
#include<iostream>
using namespace std;
class Complex
{
	public:
		Complex(){real=0;imag=0;}
		Complex(double r){real=r;imag=0;}
		Complex(double r,double i){real=r;imag=i;}
		friend Complex operator+(Complex c1,Complex c2);
		void display();
	private:
		double real;
		double imag;
};
Complex operator+(Complex c1,Complex c2)
{
	return Complex(c1.real+c2.real,c1.imag+c2.imag);
}
void Complex::display()
{
	cout<<"("<<real<<","<<imag<<"i)"<<endl;
}
int main()
{
	Complex c1(3,4),c2(5,-10),c3;
	c3=c1+2.5;
	c3.display();
	return 0;
}

在已经定义了相应的转换构造函数情况下,将运算符“+”函数重载为友元函数,在进行两个复数相加时可以用交换律。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值