运算符重载

基本概念

可以重载为普通函数,也可以重载为成员函数
重载为成员函数时,参数个数为 操作数个数 减一
重载为普通函数时,参数个数为 操作数个数

Complex operator+(const Complex &a,const Complex &b){
	return Complex(a.real+b.real,a.imag+b.imag);		// 返回一个临时对象
}
返回值类型 operator运算符(形参表){
	....
}

无名临时对象: typename();
complex();
complex(4,5);
Complex(a.real+b.real,a.imag+b.imag);

赋值运算符的重载

赋值运算符 = 只能重载为 成员函数

class String{
private:
	char *str;
public:
	String():str(new char[1]){			// 构造函数  无参
		str[0]=0;
	}
	String& operator= (const char *s);		// 运算符 重载 
	~String(){								// 析构 
		delete [] str;
	}
};
String& String::operator= (const char *s){
	delete []str;	// 释放
	str=new char[strlen(s)+1];	// 再次申请
	strcpy(str,s);	// 将 s 里的 '\0' 也赋给 str了
	return *this;
}
int main(){
	String s;// 调用 构造函数
	s="good luck,";				// 实质: s.operator=("good luck,");
	s="shenzhou 8!";			// 实质: s.operator=("shenzhou 8!");
}

深拷贝与浅拷贝

String S1,S2;
S1="this";
S2="that";
S1=S2;
此时S1.str 和 S2.str 均指向同一片空间  "that"

引发的几个问题:

  • S1的 str 指向 “this”,执行 S1=S2 后,S1的 str 指向了 “that”,存放 “this” 的存储空间 没有释放,以后他也没有机会被 delete。
  • 如果 S1对象消亡,析构函数将释放S1.str 指向的空间,S2消亡时还要释放一次.但只能释放一次,故会报错。
  • 如果再去执行 S1=“other”;则会导致 S2.str指向的地方被 delete

因此,需要添加一个 重载;

String& operator=(const String & s){
	delete []str;	// "释放 this" 
	str=new char[strlen(s.str)+1];		// 开辟新空间 
	strcpy(str,s.str);
	return * this;
}

非引用的函数返回值不可以作为左值使用
所以,如果 返回值 是 String
则,(a=b)=c; 就是不可以的。改成 String & 后,(a=b)返回a的引用,这样可以。

同样的,如果不写复制构造函数,在执行 CArray a2(a1); 时,a2的成员变量指针 也是和 a1中的指针变量指向同一片空间,并不会开辟新空间。

运算符重载为友元函数

有时候,重载为成员函数不能满足我们的要求。比如:

class Complex{
double real,imag;
public:
	Complex(double r,double i):real(r),imag(i){
	}
	Complex operator+(double r);
};

这可以很好的解决 c+5,(c是 Complex类的一个对象),但处理不了 5+c
所以改为:

在 Complex类里声明为 友元
Complex operator+(double r,const Complex &c){
	return Complex(c.real+r,c.imag);
}

流插入运算符和流提取运算符的重载

将 s 对象 以某种形式 输出
cout<<s;
// 因为 << 和 >> 只会作用到左边 cout身上, 而不会作用到 右边 s 身上, 所以我们只能写成全局的。
s<<cout;		// 当然也可以这样写, 但是不符合习惯

cout 是 ostream类的一个对象

cout<<5<<"this";
本质:cout.operator<<(5).operator<<("this");


重载成全局函数时,参数个数 等于 操作数个数。因为是 cout<<s;
所以重载成全局函数时,第一个参数对应 cout,第二个参数对应 s

假定 c 是Complex复数类的对象,希望 cout<<c; 就可以输出 a+bi 的形式。cin>>c;,就可以从键盘接受 a+bi 形式的输入。

class Complex{
double real,imag;
public:
	Complex(double r=0,double i=0):real(r),imag(i){
	}
	friend ostream& operator<<(ostream &os,const Complex &c);
	friend istream& operator>>(istream &is,Complex &c);
};

ostream& operator<<(ostream &os,const Complex &c){
	os<<c.real<<"+"<<c.imag<<"i";
	return os;
}
istream& operator>>(istream &is, Complex &c){
	string s;
	is>>s;		// 读入"a+bi"
	int pos=s.find("+",0);
	string sTemp=s.substr(0,pos);	// 分离出实部数字 
	c.real=atof(sTemp.c_str());
	sTemp=s.substr(pos+1,s.length()-pos-2);	// 分离出虚部数字 
	c.imag=atof(sTemp.c_str());
	return is;
}
int main(){
	Complex c;
	cin>>c;
	cout<<c; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值