C++中,+-*/之类的运算一般只能运用于基本数据类型之间,当然系统默认也有重载,否则字符串也就不能相连了。为了复合数据类型的运算方便,C++提供了运算符重载机制,可以进行类之间的运算。
在这里,需要强调的是,运算符重载函数也是函数,也是相当于使用对象调用的,只是一般使用的时候隐藏了调用过程。例如Complex++; 相当于complex.operator++();。下面分步骤详细介绍常用运算符重载。
1. 首先介绍+运算符重载。由于+常见的用法就是求和,所以此处也是以求和为例,代码如下。
Complex operator+(const Complex &x) const
{
Complex c(this->a+x.a,this->b+x.b);
return c;
}
注:第一个const修饰的x对象,说明x的变量不能更改。第二个const修饰的说明当前对象,相当于this的变量不能被更改。
2. 下面介绍前置自加运算符++的重载,需要注意的是和后置++做区分,具体代码如下。
Complex& operator++()
{
this->a++;
this->b++;
return *this;
}
注:返回值应为当前对象的引用。
3.下面介绍与之类似的后置自加运算符++的重载,c++底层为了区分两个重载方法,特在后置重载方法中传入一个int型参数,这个参数只是起个区分作用,具体代码如下所示。
Complex& operator++(int)
{
this->a++;
this->b++;
return *this;
}
4. 有时候,为了实现深拷贝功能,需要重载=运算符,具体代码如下所示。
Complex& operator=(const Complex& V)
{
this->a=V.a;
this->b=V.b;
return *this;
}
5. 其余常用的运算符还有判断等于与否,具体代码如下所示。
bool operator==(const Complex& V) const //重载==
{
return (this->a==V.a)&&(this->b==b);
}
bool operator!=(const Complex& V) const //重载!=
{
return (this->a!=V.a)||(this->b!=V.b);
}
6.最后介绍和上似情况不同的cin和cout对象的重载,对比一下上述运算符,我们会发现它们都是当前类对象调用的方法,所以类比一下,如果我们想将cin或者cout实现重载,必须写在它们对应的类iostrem或者outstream中,然并卵,C++并没有提供源码,所以只能采用“曲线救国”的方式实现这两个运算符重载,即全局函数。
这时候有一个问题就出现了,在类外面,要想访问类中的私有成员,或者将成员变量声明成public,破坏类的整体结构,或者将函数声明为友元函数,这样类中的成员变量相对于此函数来说,全部相当于public声明。当然,友元类也是这个道理。下面详细介绍实现的全局函数,具体代码如下所示。
ostream& operator<<(ostream &out,Complex &c) //<<使用全局函数实现输出重载
{
out<<c.a<<" "<<c.b<<endl;
return out;
}
friend ostream& operator<<(ostream &out,Complex &c); //在类中声明友元函数,会屏蔽public或者private关键字
注:参数顺序不能错,细想一下,out的位置可能相当于类中方法隐藏的vptr指针吧。
7. 不能重载的运算符包括:. :: .* ?: sizeof
需要注意的是,重载运算符只是对运算符做出了新的解释,它的原有语义不变。
1>不改变运算符的优先级
2>不改变运算符的结合性
3>不改变运算符所需要的操作数
4>不能创建新的运算符