zoukankan      html  css  js  c++  java
  • C++--第13课

    第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 ", 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 ");

        }

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

        {

            a1[i] = i + 1;

        }

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

        {

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

        }

        a3 = a2 = a1;

        if( a1 == a2 )

        {

            printf("a1 == a2 ");

        }

       

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

        {

            printf("Element %d: %d ", 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++中不要重载&&和||操作符。

  • 相关阅读:
    两个错误的解决方案
    利用BeautifulSoup爬去我爱我家的租房数据
    使用Docker安装PaddlePaddle安装过程中出现的几个问题
    将博客搬至CSDN
    iOS---实现在屏幕上实时绘图的简单效果---CAShaperLayer和UIBezierPath的简单运用
    举例理解Hibernate的三种状态(转)
    关于hibernate5的映射文件和配置文件改变(转)
    数据库事务四种隔离级别
    使用idea构建Hibernate5项目
    手把手教你如何把java代码,打包成jar文件以及转换为exe可执行文件
  • 原文地址:https://www.cnblogs.com/free-1122/p/11336208.html
Copyright © 2011-2022 走看看