C++运算符重载——郭炜

初识运算符重载

● 对已经预定义的运算符赋予多重含义,使同一运算作用于不同的数据类型的时候有不同的类型行为
● 不能重载对内部C++数据类型进行操作的运算符
● 同一运算符,对不同类型的操作数,行为不一样
● 运算符重载实际上是函数重载,成员函数或是普通函数
● 把含有运算符的表达式转化成函数调用,这个表达式中的操作数实际上就变成了函数的参数
● 同一个运算符可以多次重载,多个重载函数。
● 只有赋值运算符不能继承

结构:

返回值类型 operate 运算符 (形参){ }
class Complex
{
	public:
		double real,imag;
	Complex(double r= 0.0,double i=0.0):real(r),imag(i)//这个参数列表是缺省的
	Complex operator-(const Complex & c);             //所以在调用构造函数的时候可以不给参数
};
Complex operator+ (const Complex &a ,const Complex &b){
	return Complex(a.real+b.reall,a.imag-b.imag);//返回一个临时对象
}
Complex Complex::operator- (const Complex &c){
	return Complex(real-c.reall,imag-c.imag);
}
int main{
	Complex a(4,4),b(1,1);
	c = a+b;//c=operator(a,b);
	(a-b)//a.operator-(b)
}

重载为成员函数时,参数个数运算符目数减一
重载为普通函数时,参数个数为运算符目数

运算符重载的注意事项
1、不能定义新的运算符
2、不能改变运算符的优先级和结合性
3、 “.*” “::” “?:” “.” sizeof: 不能重载
new delete 可以重载
4、() [] -> =重载时必须声明成类的成员函数

赋值运算符的重载

只能重载为成员函数
注意变量初始化中的等号不是赋值等号,而是调用了复制构造函数
String & operator = (const String & s){
	if(this==&s)//防止自身=自身时出错 
			return *this;
	detele [] str;
	str = new char(strlen(s.str)+1);
	strcpy(str,s.str);
	return *this;
}

返回值为什么用Sting &?
a = b = c;为了能够连等,返回值就得是String
(a=b) = c; a=b的值是a的引用,这样才能把c的值复制给a=b;
所以需要使用string &
等价于:
a.operator=(b.operator=( c ));
(a.operator=(b)).operator=( c );

浅拷贝和深拷贝
浅拷贝
当类的成员变量是一个指针的时候
直接令两个对象相等的话,会使两个对象的指针变量指向同一片地方
浅拷贝

深拷贝
这个时候需要重载赋值运算符
赋值之后使两个对象的指针指向两片独立的内存
这种情况下必须重写复制构造函数
深拷贝
赋值符和赋值构造函数使用的时机
赋值构造函数:为新生产的对象赋值就是复制构造函数起作用:A a1=a2; A a1(a2);
赋值符:把一个已经生成的对象赋值给另一个已经存在的对象

运算符重载为友元函数

有时,重载为成员函数不能满足使用要求,重载为普通函数,又不能访问类的私有成员,所以需要将运算符重载为友元。
class Complex
{
	double real,imag;
	public:
		Complex (double r,double i):real(r),imag(i){};
		Complex operator+(double r);
		friend Complex operator+(double r,const Complex &c);//若不这样做,只能实现c+5,而不能实现5+c

}
Complex Complex::operator+(double r){//可以接受c+5
	return Complex(this.real+r,this.imag);
}
Complex operator+(double r,const Complex &c){//可以接受5+c
	return Complex(c.real+r,c.imag);
}

<< >> 的重载

一般重载为普通函数
在使用的时候常常声明为类的友元函数
若重载为类的成员函数,不会节省一个参数,习惯上声明为友元函数
class Complex
{
	private:
		double a;
		double b;
	public:
		Complex(double x=0,double y=0):a(x),b(y){};//这里有个分号
		friend ostream & operator<<(ostream & os,const Complex & c);
		friend istream & operator>>(istream & is,const Complex & c);
};
ostream & operator<<(ostream & os,const Complex & c){
	os<<c.a<<"+"<<c.b<<"i";//以“a+bi”的形式输出
	return os;
}
istream & operator<<(istream & is,const Complex & c){
	String s;
	is>>s;
	//从s分割出来实部虚部
	c.a = s.a;//伪码
	c.b = s.b;//伪码
	return is;
}

类型转换运算符

不用写明返回值类型,返回类型就是这个类型转换运算符的本身的类型
class Complex{
	private:
		double a;
		double b;
	public:
		Complex(double x=0,double y=0):a(x),b(y){};//这里有个分号
		operator double (){return a;}
}
int main(){
	Complex c(1.2,3.4);
	cout << (double)c <<endl;//这个表达式的返回值就是c的实部
	double n = 2+c;//这里的+号没有重载但还是能够通过编译
					//自动转化!等价于double n=2+c.operator double()

}

自增、自减运算法的重载

++ --有前置和后置之分
前置运算符作为一元运算符重载 
后置运算符作为二元运算符重载,多一个没有的参数
只重载前置的话,后置可能会调用前置,或者直接出错
int main{
	CDemo d(5);
	cout << (d++) << ",";
	cout << d << ",";
	cout << (++d) << ",";
	cout << d << ",";
	cout << (d--) << ",";
	cout << d << ",";
	cout << (--d) << ",";
	cout << d << ",";
}
//要求输出结果 5,6,7,7 7,6,5,5
int a;
(++a) = 1;//这样写不出错,因为++a返回的是a的引用
(a++) = a;//这样写出错,因为这个时候返回的是一个临时对象,就是a在加之前的值
//因为以上的原因我们在重载的时候必须保持这样的特性:

重载代码如下:

class CDemo
{
	private:int d;
	public:
		CDemo(int n = 0):d(n){};
		CDemo & operator++();//这里的&是为了维持原来的特性
		CDemo operator++(int);
		friend CDemo operator--(CDemo &,int );//这里不能写变量名
		friend CDemo & operator--(CDemo &);
		operator int (){return d;}
}
CDemo & CDemo::operator++(){
	d++;
	return *this;
}
CDemo CDemo::operator++(int k ){
	CDemo tmp(*this);
	d++;
	return (tmp);
}
CDemo operator--(CDemo & c,int );{//这里的引用是为了修改对象的值
	CDemo tmp(*this);
	c.d--;
	reutrn tmp;
}
CDemo & operator--(CDemo & c){//这里不能有const因为要修改这个对象的值
	c.d--;
	reutrn c;
}

++i的效率要比i++的效率要高
i++要多调用一个复制构造函数,效率低。

[ ] ( ) 重载

只能重载成类的成员函数

声明格式:

< 类型 > operator []<参数表>;
< 类型 > operator ()<参数表>;

调用格式:

Per p;//生产对象
p();// p.()
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值