运算符重载

运算符重载就是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据时导致不同的行为。

运算符重载的规则

(1)C++中的运算符除了少数几个之外,全部都可以重载,而且只能重载C++中已经有的运算符。
(2)重载之后运算符的优先级和结合性都不会改变。
(3)运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造。重载运算符函数可以对运算符做出新的解释,但原有基本语义不变:不改变运算符的优先级,结合性,所需要的操作数,并且不会创建新的运算符。

运算符重载为成员函数

例:将复数类加减法重载运算为函数成员形式

#include <iostream>
using namespace std;

class Complex {                                                
public:                                                        
    Complex(double r = 0.0, double i = 0.0) :real(r), imag(i) {}       
    Complex operator+(const Complex& c2) const;//运算符+重载函数成员
    Complex operator-(const Complex& c2) const;//运算符-重载函数成员
    void display() const;//显示复数的值
private:
    double real, imag; //复数虚部和实部
};
Complex Complex::operator+(const Complex& c2) const {  //重载运算符函数实现
    return Complex(real + c2.real, imag + c2.imag);//创建一个临时无名对象作为返回值
}

Complex Complex::operator-(const Complex& c2) const { //重载运算符函数实现
    return Complex(real - c2.real, imag - c2.imag);//创建一个临时无名对象作为返回值
}

void Complex::display() const {
    cout << "(" << real << "," << imag << ")" << endl;
}

int main() {
    Complex c1(5, 4), c2(2, 10), c3;
    cout << "c1=";
    c1.display();
    cout << "c2=";
    c2.display();
    c3 = c1 - c2; //使用重载运算符完成复数减法
    cout << "c3=c1-c2=";
    c3.display();
    c3 = c1 + c2;
    cout << "c3=c1+c2";//使用重载运算符完成复数减法
    c3.display();
    return 0;
}

//运行结果
//c1=(5,4);
//c2=(2,10);
//c3=c1-c2=(3,-6);
//c3=c1+c2=(7,14);

除了在函数声明及实现的时候使用了关键字operator之外,运算符重载成员函数与类的普通成员函数没有什么区别。在使用的时候,可以直接通过运算符、操作数的方式来完成函数调用。这时,运算符“+”,“-”原有的功能都不改变,对整型数、浮点数等基本类型数据的运算仍然遵循C++预定义的规则,同时添加了新的针对复数运算的功能。“+”这个运算符,作用于不同的对象上,就会导致完全不同的操作行为,具有了更广泛的多态特征。

运算符重载为非成员函数

例:以非成员函数形式重载Complex的加减法运算和“<<”运算符。

#include<iostream>
using namespace std;

class Complex {
public:
    Complex(double r=0.0,double i=0.0):real(r),imag(i){}
    friend Complex operator+(const Complex& c1, const Complex& c2);//运算符+重载
    friend Complex operator-(const Complex& c1, const Complex& c2);//运算符-重载
    friend ostream& operator<<(ostream& out, const Complex& c);//运算符<<重载
private:
    double real, imag;
};
Complex operator+(const Complex& c1, const Complex& c2) {//重载运算符函数实现
    return Complex(c1.real + c2.real, c1.imag + c2.imag);
}
Complex operator-(const Complex& c1, const Complex& c2) {
    return Complex(c1.real - c2.real, c1.imag - c2.imag);
}
ostream& operator<<(ostream& out, const Complex& c) {//重载运算符函数实现
    out << "(" << c.real << "," << c.imag << ")";
    return out;
}
int main() {
    Complex c1(5, 4), c2(2, 10), c3;
    cout << "c1=" << c1 << endl;
    cout << "c2=" << c2 << endl;
    c3 = c1 - c2;
    cout << "c3=c1-c2=" << c3 << endl;
    c3 = c1 + c2;
    cout << "c3=c1+c2=" << c3 << endl;
    return 0;
}
//程序运行结果完全同上

运算符的两种重载形式各有千秋。成员函数的重载方式更加方便,但有时出于以下原因,需要使用非成员函数的重载方式。
(1)要重载的操作符的第一个操作数不是可以更改的类型,例如上例中“<<”运算符的第一个操作数的类型为ostream,是标准库的类型,无法向其中添加成员函数。
(2)以非成员函数形式重载,支持更灵活的类型转换。