C++--第13课 - 操作符重载 - 下

99封情书 提交于 2019-11-27 00:10:56

第13课 - 操作符重载 - 下

思考:

通过operator关键字能够将操作符定义为全局函数,操作符重载的本质就是函数重载。类的成员函数是否可以作为操作符重载的函数?

 

1. operator+的成员函数实现

#include <cstdlib>

#include <iostream>

using namespace std;

class Complex

{

    int a;

    int b;

public:

    Complex(int a, int b)

    {

        this->a = a;

        this->b = b;

    } 

    int getA()

    {

        return a;

    }  

    int getB()

    {

        return b;

    }   

    Complex operator+ (const Complex& c2);

//看上去只有一个参数,实际有俩,另一个是this指针 

    friend ostream& operator<< (ostream& out, const Complex& c);

};

ostream& operator<< (ostream& out, const Complex& c)

{

    out<<c.a<<" + "<<c.b<<"i";

   

    return out;

}

Complex Complex::operator+ (const Complex& c2)

{

    Complex ret(0, 0);

   

    ret.a = this->a + c2.a;

    ret.b = this->b + c2.b;  

    return ret;

}

int main(int argc, char *argv[])

{

    Complex c1(1, 2);

    Complex c2(3, 4);

    Complex c3 = c1 + c2;  

    cout<<c1<<endl;

    cout<<c2<<endl;

    cout<<c3<<endl;  

    cout << "Press the enter key to continue ...";

    cin.get();

    return EXIT_SUCCESS;

}

运行结果:

1 + 2i

3 + 4i

4 + 6i

用成员函数重载的操作符,比全局操作符重载函数少一个参数,即左操作数。另外也不需要使用friend关键字。

Complex c1(1, 2);

Complex c2(3, 4);

Complex c3 = c1 + c2;

等价于

Complex c1(1, 2);

Complex c2(3, 4);

Complex c3 = c1.operator+ c2;

操作符的重载实际上就都是函数来实现的。

 

问:

什么时候使用全局函数重载操作符?什么时候使用全局函数重载操作符?

答:

当无法修改左操作数的类时,使用全局函数进行重载。

=, [], ()和->操作符只能通过成员函数进行重载。

 

2. 代码—数组的改进

重载赋值操作符,重载数组操作符,重载比较操作符。

C++编译器会为每个类提供默认的赋值操作符。默认的赋值操作符只是做简单的值复制。

类中存在指针成员变量时就需要重载赋值操作符。

Array.h

#ifndef _ARRAY_H_

#define _ARRAY_H_

class Array

{

private:

    int mLength;

    int* mSpace;

public:

    Array(int length);

    Array(const Array& obj);

    int length();

    ~Array();

    int& operator[](int i);

    Array& operator= (const Array& obj);

    bool operator== (const Array& obj);

    bool operator!= (const Array& obj);

};

#endif

 

Array.cpp

#include <stdio.h>

#include "Array.h"

Array::Array(int length)

{

    if( length < 0 )

    {

        length = 0;

    }  

    mLength = length;

    mSpace = new int[mLength];

}

Array::Array(const Array& obj)

{

    mLength = obj.mLength;

    mSpace = new int[mLength]; 

    for(int i=0; i<mLength; i++)

    {

        mSpace[i] = obj.mSpace[i];

    }

}

int Array::length()

{

    return mLength;

}

Array::~Array()

{

    mLength = -1;

    printf("%08X\n", mSpace);

    delete[] mSpace;

}

int& Array::operator[](int i)

{

    return mSpace[i];

}

Array& Array::operator= (const Array& obj)

{

    delete[] mSpace; 

    mLength = obj.mLength;

    mSpace = new int[mLength];  

    for(int i=0; i<mLength; i++)

    {

        mSpace[i] = obj.mSpace[i];

    }   

    return *this;

}

bool Array::operator == (const Array& obj)

{

    bool ret = true;

    if( mLength == obj.mLength )

    {

        for(int i=0; i<mLength; i++)

        {

            if( mSpace[i] != obj.mSpace[i] )

            {

                ret = false;

                break;

            }

        }

    }

    else

    {

        ret = false;

    }   

    return ret;

}

bool Array::operator!= (const Array& obj)

{

    return !(*this == obj);

}

 

 

main.c

#include <stdio.h>

#include "Array.h"

int main()

{

    Array a1(10);

    Array a2(0);

    Array a3(0);

    if( a1 != a2 )

    {

        printf("a1 != a2\n");

    }

    for(int i=0; i<a1.length(); i++)

    {

        a1[i] = i + 1;

    }

    for(int i=0; i<a1.length(); i++)

    {

        printf("Element %d: %d\n", i, a1[i]);

    }

    a3 = a2 = a1;

    if( a1 == a2 )

    {

        printf("a1 == a2\n");

    }

   

    for(int i=0; i<a2.length(); i++)

    {

        printf("Element %d: %d\n", i, a2[i]);

    }

    printf("Press any key to continue...");

    getchar();

    return 0;

}

 

3. 要点

C++编译器会为每个类提供默认的赋值操作符。

默认的赋值操作符只是做简单的值复制。

类中存在指针成员变量时就需要重载赋值操作符。

 

l  ++操作符的重载(--操作符是一样的)

++操作符只有一个操作数.

++操作符有前缀和有后缀的区分

 

 

l  如何重载++操作符才能区,分前置运算和后置运算?

操作符重载是通过函数重载实现的,C++中通过一个占位参数来区分前置运算和后置运算。

#include <cstdlib>

#include <iostream>

using namespace std;

class Complex

{

    int a;

    int b;

public:

    Complex(int a, int b)

    {

        this->a = a;

        this->b = b;

    }

    int getA()

    {

        return a;

    }

    int getB()

    {

        return b;

    } 

    Complex operator+ (const Complex& c2);

    Complex operator++ (int); // obj++

    Complex& operator++(); // ++obj

    friend ostream& operator<< (ostream& out, const Complex& c);

};

ostream& operator<< (ostream& out, const Complex& c)

{

    out<<c.a<<" + "<<c.b<<"i";

    return out;

}

Complex Complex::operator++ (int) //具体的实现

{

    Complex ret = *this;  //拷贝构造函数,将当前的值拷贝到ret中。

    a++;

    b++;

    return ret; 

}

Complex& Complex::operator++()  //具体的实现

{

    ++a;

    ++b; 

    return *this;

}

//以上连个函数说明前置的++效率更高。

Complex Complex::operator+ (const Complex& c2)

{

    Complex ret(0, 0);  

    ret.a = this->a + c2.a;

    ret.b = this->b + c2.b; 

    return ret;

}

int main(int argc, char *argv[])

{

    Complex c1(1, 2);

    Complex c2(3, 4);

    Complex c3 = c2;

    c2++;

    ++c3;  

    cout<<c1<<endl;

    cout<<c2<<endl;

    cout<<c3<<endl;  

    cout << "Press the enter key to continue ...";

    cin.get();

    return EXIT_SUCCESS;

}

 

4. 为什么不能重载&&和||操作符

从语法的角度可以重载,但是最好不要,容易出错。

#include <cstdlib>

#include <iostream>

using namespace std;

class Test

{

    int i;

public:

    Test(int i)

    {

        this->i = i;

    } 

    Test operator+ (const Test& obj)  //加法操作符重载

    {

        Test ret(0);

       

        cout<<"Test operator+ (const Test& obj)"<<endl;

       

        ret.i = i + obj.i;

       

        return ret;

    }

    bool operator&& (const Test& obj)  //与运算操作符重载

    {

        cout<<"bool operator&& (const Test& obj)"<<endl;

       

        return i && obj.i;

    }

};

int main(int argc, char *argv[])

{

    int a1 = 0;

    int a2 = 1;

    if( a1 && (a1 + a2) )

    {

        cout<<"Hello"<<endl;

    }

    Test t1 = 0;

    Test t2 = 1; 

    if( t1 && (t1 + t2) )

    {

        cout<<"World"<<endl;

    }

    cout << "Press the enter key to continue ...";

    cin.get();

    return EXIT_SUCCESS;

}

运行结果:

Test operator+ (const Test& obj)

bool operator&& (const Test& obj)

l  &&和||是C++中非常特殊的操作符。

l  &&和||内置实现了短路规则。

l  操作符重载是靠函数重载来完成的。

l  操作数作为函数参数传递。

l  C++的函数参数都会被求值,无法实现短路规则。

 

小结:

操作符重载可以直接使用类的成员函数实现。

=, [], ()和->操作符只能通过成员函数进行重载。

++操作符通过一个int参数进行前置与后置的重载。

C++中不要重载&&和||操作符。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!