重新C++系列之运算符重载

一、什么是运算符重载

        简单来讲就是对运算符赋予新的意义,但是又不能改变原有的含义,它本身也就是一个函数。运算符重载的本质是以函数的方式来体现。

二、运算符重载有几种

        1、按照作用域来划分,有全局操作符重载函数和成员函数操作符重载函数。

        2、按照操作数个数来划分,有单目运算符重载和双目运算符重载。

        通常来讲,往往把输入流和输出流运算符改写为全局操作符重载函数,普通的运算符改写为成员函数操作符重载函数。如果想要使用成员函数来重载输出流《 和 输入流》,必须在C++库中对应的类加入这个重载的成员函数,不建议使用。

三、运算符重载的特性

        1、不能新增运算符,只能对已有的C++运算符进行重载。

        2、不能改变操作数的个数,运算符重载后仍是原有操作数个数。

        3、尽量不改变语义,应当使重载运算符功能是类似相同。

        4、并不是所有的运算符都可以重载,以下5个运算符不能重载作用域运算符::,成员访问运算符.,类型长度运算符sizeof(),成员指针运算符.*,条件运算符?:

四、怎么实现运算符重载

        采用普通函数的调用方式来调用运算符重载函数,基本语法如下:

// 关键字operator不能省略
// 函数名:operator 运算符
// 参数列表:操作数的个数受原有运算符的操作数个数限定

返回值 operator 运算符(参数列表)
{
    // 重载函数体
}

五、案例

        1、运算符重载的简单使用

#include 

using namespace std;

// 复数类
class Complex
{
private:
    int a;  // 实部
    int b;  // 虚部
public:
    Complex(int a = 0, int b = 0)
    {
        this->a = a;
        this->b = b;
    }
    void show()
    {
        if(b < 0)
        {
            cout << a << b << "i" << endl;
        }
        else
        {
            cout << a << "+" << b << "i" << endl;
        }

    }
    // 重载运算符+
    Complex& operator + (const Complex& op)
    {
        static Complex temp;
        temp.a = this->a + op.a;
        temp.b = this->b + op.b;
        return temp;
    }
    // 重载运算符-
    Complex& operator - (const Complex& op)
    {
        static Complex temp;
        temp.a = this->a - op.a;
        temp.b = this->b - op.b;
        return temp;
    }
    // 重载运算符*
    Complex& operator * (const Complex& op)
    {
        static Complex temp;
        temp.a = this->a*op.a - this->b*op.b;
        temp.b = this->a*op.b + this->b*op.a;
        return temp;
    }
    // 重载运算符 / 
    Complex& operator / (const Complex& op)
    {
        static Complex temp;
        int x = op.a*op.a + op.b*op.b;
        temp.a = (this->a*op.a + this->b*op.b)/x;
        temp.b = (this->b*op.a - this->a*op.b)/x;
        return temp;
    }
    bool operator == (const Complex& op)
    {
       return (this->a == op.a && this->b == op.b);
    }

};


int main()
{
    Complex A(1, 2);
    Complex B(1, 2);

    if(A == B)
    {
        cout << "A == B" << endl;
    }

    Complex C = A + B;
    cout << "C = ";
    C.show();

    Complex D = A - B;
    cout << "D = ";
    D.show();

    Complex E = A * B;
    cout << "E = ";
    E.show();

    Complex F = A / B;
    cout << "F = ";
    F.show();


    return 0;
}


重新C++系列之运算符重载_第1张图片

        2、全局操作符重载示例

#include 

using namespace std;

// 复数类
class Complex
{
private:
    int a;  // 实部
    int b;  // 虚部
public:
    Complex(int a = 0, int b = 0)
    {
        this->a = a;
        this->b = b;
    }
    void show()
    {
        if(b < 0)
        {
            cout << a << b << "i" << endl;
        }
        else
        {
            cout << a << "+" << b << "i" << endl;
        }

    }
    
    // 全局操作符重载,重载输入流和输出流,为了方便通常声明friend友元函数
    friend ostream& operator << (ostream & output, const Complex & other);
    friend istream& operator >> (istream & input,  Complex & other);


};
// 可以改为以下定义,但是后面不能连续输入对象,即cout<< A << endl;是非法的,只能cout << A;
// void operator << (ostream & output, const Complex & other)

ostream& operator << (ostream & output, const Complex & other)
{
    if(other.b < 0)
    {
        output << other.a << other.b << "i";
    }
    else
    {
        cout << other.a << "+" << other.b << "i";
    }

    return output;

}

// 可以改为以下定义,但是后面不能连续输入对象,即cin>>A>>B;是非法的,只能cin>>A; cin>>B;
// void operator >> (istream & output, const Complex & other)
istream& operator >> (istream & input,  Complex & other)
{
    input >> other.a >> other.b;
    return input;
}

int main()
{
    Complex A;
    Complex B;
    cin >> A >> B;  // 可以连续输入类对象
    cout << "A = ";
    A.show();

    cout << "B = " << B << endl;
    

    return 0;
}

重新C++系列之运算符重载_第2张图片

        3、[]运算符和()运算符

#include 

using namespace std;


class Test
{
private:
    int *a;
    int len;
public:
    Test(int len = 1)
    {
        this->len = len;
        if(len <= 0)
        {
            cout << "len is less than 0" << endl;
            return;
        }
        a = new int[len];
    }

    ~Test()
    {
        if(a != nullptr)
        {
            delete [] a;
            a = nullptr;
        }
    }

    // 重载[]运算符函数
    int& operator[](int index)
    {
        return a[index];
    }
    // 重载()运算符函数,变成所谓的仿函数,可以用类对象来作为函数名
    void operator()(int len)
    {
        for(int i = 0; i < len; i++)
        {
            cout << a[i] << " "; 
        }
        cout << endl;
    }

};


int main()
{
    
    Test temp(5);
    
    for(int i = 0; i < 5; i++)
    {
        temp[i] = i+1;  // 像数组那样来操作
    }
    
    temp(5);    // 像调用函数那样来操作

    return 0;
}

六、总结

        运算符重载通常是为了更加方便的操作类对象,但是并不是所有的运算符都可以重载,重载的运算符应该尽量跟原来运算符的含义相似,同时不能创造新的不属于C++的运算符。

你可能感兴趣的:(C++语言设计,c++)