基本概念
可以重载为普通函数,也可以重载为成员函数
重载为成员函数时,参数个数为 操作数个数 减一
重载为普通函数时,参数个数为 操作数个数
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;
}