C++回顾之运算符重载

        前面回顾了C++的友元函数及友元类的相关要点。本文主要讲述运算符的重载,它也与友元有部分的关联。为什么在C++中需要进行运算符重载呢?主要有下面几个原因:

        (1) 对于标准类型的数据,如int, double都可以进行加、减、乘、除、大于、小于比较等运算,这是很直观的。而C++的类对象默认是没有这些功能的。如果要实现类对象的这些运算,可以自己定义成员函数,通过函数调用的方式来实现,如obj1.Add(obj2)这种方式不直观,而如果能实现obj1 = obj1 - obj2; 这与标准类型的数据计算方式是一样的,而这是我们最容易接受的,因为很熟悉,所以一看便知。所以,在C++中,运算符重载允许把一些标准的运算符(加、减、乘、除、大于、小于比较等运算)应用于自定义类型的类对象中。

        (2) 程序员阅读程序时,直观,自然,提高可读性。

        (3) 此外,可以体现C++的可扩充性。

       

        运算符重载虽然有好处,但是也需要注意一些要点:

        (1) 运算符重载只是语法上的方便,它只是另一种函数调用的方式

        (2) 运算符重载的本质还是函数重载

        (3) 不要滥用重载,只有在涉及的代码更容易写,尤其是更易读时才有必要重载。

          

        运算符重载的实现方式有2种:成员函数重载和非成员函数重载(友元函数重载),

        成员函数重载的原型: 函数类型  operator运算符(参数表)

        成员函数定义的格式:函数类型 类名::operator运算符(参数表){函数体;}


        非成员函数重载的原型:friend 函数类型 operator运算符(参数表)

        非成员函数定义的原型:函数类型 operator运算符(参数表){函数体;}


        下面举一个复数类complex重载的例子:         

#ifndef _COMPLEX_H
#define _COMPLEX_H

class complex
{
public:
    complex(int real, int imag):real_(real),imag_(imag){}
    complex();
    ~complex();

    complex& Add(const complex& other);
    void Display() const;
    
    complex operator+(const complex& other); //成员函数重载
    friend complex operator+(const complex& c1, const complex& c2); //友元函数重载

private:
    int real_; //复数的实部
    int imag_; //虚部
};

#endif

       下面是类的具体实现:

        

#include <iostream>
#include "complex.h"
using namespace std;

complex::complex(){cout << "complex..."<<endl;}
complex::~complex(){cout << "~complex"<<endl;}

void complex::Display() const
{
    cout <<real_<<"+"<<imag_<<"i"<<endl;
}

complex& complex::Add(const complex& other)
{
    real_ += other.real_;
    imag_ += other.imag_;

    return *this;
}

//成员函数重载+运算符的具体定义
complex complex::operator+(const complex& other)
{
    int r = real_ + other.real_;
    int i = imag_ + other.imag_;
    return complex(r,i);
}

//友元函数+运算符重载的具体定义:
complex operator+(const complex& c1, const complex& c2)
{
    int r = c1.real_ + c2.real_;
    int i = c1.imag_ + c2.imag_;
    return complex(r,i);
}

        下面写个简单的测试用例:

int main()
{
    complex c1(3,5);
    complex c2(4,6);

    c1.Add(c2); //c1的值发生了变化
    c1.Display();

    //等价于c1.operator+(c2)或operator+(c1,c2)
    complex c3 = c1 + c2; //此方法c1,c2值不变,将加的结果初始化为c3.

}
       需要注意一点:complex c3 = c1 + c2,它与c1.operator+(c2)或operator+(c1,c2)是一样的,也就是说,c3 = c1 + c2将调用后面两个表达式的其中一个,当运算符的成员函数与非成员函数重载时,它调用的是哪一个呢?答案是优先调用成员函数重载。如果成员函数重载没提供,只提供了友元函数重载,则将调用友元函数重载。


        下面简单说明一下运算符重载的规则:

        (1) 不允许发明新的运算符

        (2) 不能改变运算符操作对象的个数

        (3) 优先级与结合性不变

        (4) 不能重载的运算符有 ::    ?:      .(点,即域直接成员访问)      *(类成员指针引用)     sizeof

        (5) 单目运算符最好重载为类的成员函数,双目运算符则重载为类的友元函数(但=、()、[]、->除外)。

        (6) 流类型转换运算符只能以成员函数方式重载

        (7) 流运算符只能以友元的方式重载


        上面第(5)点中,为何有些双目运算符特例要重载为类的成员函数,下面来看一个简单的例子。

        

        





猜你喜欢

转载自blog.csdn.net/ab198604/article/details/19476687