重载
对已有的运算符赋予多重含义,使得同一运算符作用于不同数据类型的数据时导致不同类型的行为。
形式:返回值类型 operator 运算符(形参表){}
注意,当重载为成员函数时,参数个数为运算符数目-1.
例子:
1 | class Complex{ |
调用时:
- 赋值运算符重载
它只能重载为成员函数
简单用法如下:
问题:使用原生的赋值运算符,可以吗?答案是no。1
2
3String s1,s2;
s1="this";s2="that";
s1=s2;
看一下会出现的问题:
- this的空间失去了指针指向它,没有被delete就废弃了,产生内存垃圾。
- 如果s1消亡,析构函数会delete s1所指向的内存空间。s2也就无所指了。当s2消亡,再一次析构delete已经删除的空间,程序崩溃。
这里如果再令S2=”other”;S1指向仍是that。因为S2=”other”,是将S2指向other所在的内存地址,而不是修改S2已经指向的地址单元的值。
解决方法:
流插入和流提取运算符重载
cout是ostream类的对象,cin是istream类的对象。这两个类均定义在iostream中。
在类中分别对<<和>>进行了重载。
针对输出/输入的不同类型,c++重载了多个成员函数。
比如输出int:1
2
3
4void ostream::operator<<(int n){
......//输出n的代码
return;
}当我们想要输出特定的格式的数据时,比如复数,简单的调用cout<<输出对象肯定就不行了。自己根据需要重载<<流插入和>>流提取运算符。下面以输入输出复数类举例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21int main(){
Complex c;//Complex为复数类
int n;
cin>>c>>n;
cout<<c<<",";
return 0;
}
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);//全局函数,并声明为友元。返回值需要是ostream类的引用,即cout方便连续调用。
friend istream& opeator>>(istream& is,Complex& c);
}
ostream& operator<<(ostream& os,const Complex& c){
os<<c.real<<"+"<<c.imag<<"i";//输出以a+bi的形式
return os;
}
流提取运算符的重载类似,做一些字符串分割处理即可。注意接收键盘输入,不能为const。类型转换运算符的重载不需要写返回值
自增和自减运算符的重载
前置运算符作为一元运算符重载
后置运算符作为二元运算符重载,多写一个没用的参数
例子:要实现下面的输出,该如何重载?1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32class CDemo{
private: int n;
public:
CDemo(int i = 0):n(i){}
CDemo& operator++();//前置
CDemo operator++(int);
//后置,多一个无用参数。c++中,后置运算符没有返回引用,只是返回临时对象。
//因此i++ = 1这种写法是禁止的
//而++i返回i的引用,可以++i = x;这样的i就是x
operator int(){return n;}//重载类型转换运算符
friend CDemo& operator--(CDemo&);//声明友元,--用全局重载
friend CDemo& operator--(CDemo&,int);//后置
};
CDemo& CDemo::operator++()//前置++
{
++n;
return *this
}
CDemo CDemo::operator++(int){//后置++
CDemo temp(*this);
n++;
return temp;//返回修改前的对象,实际上n变化了。
}
CDemo operator--(CDemo& d){//前置--
d.n--;
return d;
}
CDemo operator--(CDemo& d,int){//后置--
CDemo temp(d);
d.n--;
return temp;
}
最后再补充一点重载的注意事项