C++学习笔记--操作符重载

来源:互联网 发布:windows xp系统主题 编辑:程序博客网 时间:2024/06/05 16:15

我们前面学过函数重载,知道全局函数之间可以重载,类普通成员函数和类静态成员函数之间可以进行重载,因为他们都是在同一作用域下进行的。那么重载有什么意义呢?除了函数能不能对操作符进行重载呢?

重载的意义是通过函数名对函数功能或者参数列表对函数功能进行提示,或者扩展系统中已存在的函数功能。既然能扩展函数功能,肯定也能扩展操作符的功能。

对于一个复数类,我们想要直接使用+-来进行复数对应实部虚部计算,形如下面:

class Complex{    public:        int a;        int b;        Complex(int a,int b)        {            this->a = a;            this->b = b;        }};int main(){    Complex a1(1,2);    Complex a2(2,3);    Complex a3 = a1 + a2;    return 0;}


上面的语句拿去编译肯定是会报错的,编译器发现+操作符两边的操作数不是普通的实数,因此无法识别,直接报错说操作数和+操作符无法匹配。

虽然编译器不允许我们这么直接对复数相加,我们依然可以解决,定义一个函数,两个复数类对象作为参数,函数体里分别实现实部和虚部的加法计算。这个函数可以是类成员函数,也可以是类的友元函数。虽然这样可以实现,但是复数在实际数学中的地位和实数的地位是一样的,能够实现实数之间的直接运算,那我们何不也实现让普通运算符能进行复数运算呢?

C++中的重载能够扩展操作符的功能,本质上就是用特殊形式的函数进行操作符重载。通过operator关键字可以定义这种特殊的函数来实现对操作符的重载。

使用规则如下:

格式:type operator 'sign'(const Complex& p1,const Complex& p2);举例:Complex operator + (const Complex& p1, const Complex& p2);
一些普通的运算符如+ - * / ==  !=  = 等等可以进行操作符重载。

知道了操作符重载规则后就该实战了,看一个例子:

class Complex {    int a;    int b;public:    Complex(int a = 0, int b = 0)    {        this->a = a;        this->b = b;    }    int getA(){ return a;}    int getB(){ return b;}        friend Complex operator + (const Complex& p1, const Complex& p2);};Complex operator + (const Complex& p1, const Complex& p2){    Complex ret;        ret.a = p1.a + p2.a;    ret.b = p1.b + p2.b;        return ret;}
利用友元关系实现操作符重载功能,函数实现了那么我们应该如何使用这个函数呢?

Complex c1(1, 2); Complex c2(3, 4);Complex c3 = operator +(p1,p2);//直接通过函数名调用Complex c4 = c1 + c2;//使用操作符计算

前面不是说过友元关系破坏了封装性降低了效率,我们是不是想想别的办法,比如直接将操作符重载函数作为类成员函数。

C++允许将操作符重载函数定义为类的成员函数,它有一个优势,就是比全局上的操作符重载函数少了一个参数,即左操作数。听起来是不是觉得有点怪,两个数相加为什么少了一个操作数,那是因为类成员函数有一个隐藏的参数,this指针,它可以指代左操作数以弥补函数少了一个参数。

    Complex operator + (const Complex& p)    {        Complex ret;        ret.a = this->a + p.a;        ret.b = this->b + p.b;                return ret;    }
重载实现了,现在就该使用了。我们可以将它当做成员函数来使用,也可以直接使用操作符来使用。

    Complex c1(1, 2);    Complex c2(3, 4);    Complex c3 = c1 + c2;     Complex c4 = c1.operator + (c2);

为什么说this能够充当左操作数呢,因为成员函数的调用是依靠对象的,而每个成员函数里有一个this指针指向当前对象,所以本质上还是两个操作数进行运算。

程序中同时使用了全局函数版本和类成员函数版本时编译器会进行怎样的选择呢?编译器会优先从成员函数中寻找操作符重载函数,然后再在全局作用域中查找

虽然讲解中只使用了+操作符来重载,我们也可以试验用其他操作符来进行重载,在不断试验中加深映像。

一些关于操作符重载的注意;

C++规定赋值操作符(=)只能重载为成员函数,编译器默认为每个类进行了赋值操作符的重载,但是仅仅完成浅拷贝。当需要进行深拷贝时就需要对赋值操作符进行重载,当进行赋值操作符重载时注意四小点:返回类型一定是引用,参数一定是类的const引用,判断是否自赋值(通过判断地址),返回当前对象。赋值操作符和拷贝构造函数有着同等重要的意义。

操作符重载不能改变原操作符的优先级。

操作重载符不能改变操作数的个数。

操作符重载不应该改变操作符的原有语义。

操作符重载的本质为函数定义。