• 10.操作符重载


    1.四则运算符重载

    设计一个数偶类,定义专用的四则运算

    #include <iostream>
    using namespace std;
    class Couple
    {
    public:
        Couple(int a = 0, int b = 0):_a(a),_b(b){}
        Couple operator+(const Couple &c);
        //friend Couple operator+(const Couple &c1,const Couple &c2);
        Couple operator-(const Couple &c);
        Couple operator*(const Couple &c);
        Couple operator/(const Couple &c);
        void print()
        {
            cout<<"a:"<<_a<<"	b:"<<_b<<endl;
        }
    private:
        int _a,_b;
    };
    Couple Couple::operator+(const Couple &c)
    {
        Couple _t(this->_a + c._a, this->_b + c._b);
        return _t;
    }
    /*
    Couple operator+(const Couple &c1,const Couple &c2)
    {
    	Couple _t(c1.a + c2.a, c1.b + c2.b);
    	return -t;
    }
    */
    Couple Couple::operator-(const Couple &c)
    {
        Couple _t(this->_a - c._a, this->_b - c._b);
        return _t;
    }
    Couple Couple::operator*(const Couple &c)
    {
        Couple _t(this->_a * c._a, this->_b * c._b);
        return _t;
    }
    Couple Couple::operator/(const Couple &c)
    {
        Couple _t(this->_a / c._a, this->_b / c._b);
        return _t;
    }
    
    int main()
    {
        Couple a(1,2),b(3,4),c,d;
        c = a + b;  //等价于c = a.operator+(b) ==> c(4,6)
        d = c / a;  //等价于d = c.operator/(b) ==> d(4,3)
        c.print();  //a:4  b:6
        d.print();  //a:4  b:3
        return 0;
    }
    

    涉及到的问题

    1. 参数必须是Couple类对象的常引用吗?

      可以不使用引用,但是值传递会产生对象拷贝动作,降低效率

      可以不是常引用,但无法限制函数内部对参数的修改

      可以使用指针,但与常规数学公式使用方式不符,

    2. 返回值必须是Couple类的对象吗?返回引用是否可行?

      可以返回引用,但必须是全局对象或通过参数传递进去的Couple对象的引用,不能引用函数内部的局部变量

      不建议使用引用类型的返回值

      需要将右操作数累加到左操作数上并返回左操作数时,此时应该重载加赋、减赋、乘赋、除赋、余赋等操作符

    3. 四则运算符必须重载为成员函数吗?

      可以重载为类的友元函数或普通函数。注意:普通函数无法访问类的私有成员

      建议重载为友元函数。好处:显式具有双操作数,且格式一致;操作不局限于当前对象本身,且不要求左操作数必须为本类的对象。坏处:显式具有双操作数,不能省略左操作数

    2.关系运算符重载

    为数偶类定义专门的关系操作符

    class Couple
    {
    public:
    	Couple(int a = 0, b = 0):_a(),_b(){}
        friend bool operator==(const Couple &c1,const Couple &c2);
        friend bool operator!=(const Couple &c1,const Couple &c2);
    private:
    	int _a,_b;    
    };
    bool operator==(const Couple &c1,const Couple &c2)
    {
        return (c1._a==c2._a)&&(c1.b==c2._b);
    }
    bool operator!=(const Couple &c1,const Couple &c2)
    {
        return (c1._a!=c2._a)||(c1._b!=c2._b);
    }
    int main()
    {
        Couple a(1,2),b(2,1),c(1,2);
        cout<<“a=b?”<<char(a==b?'y':'n')<<endl;
        cout<<"a!=b"<<char(a!=b?'y':'n'<<endl;
    }
    

    3.下标操作符重载

    下标操作符重载的场合于目的

    • 如果对象具有数组成员,且该成员为主要成员,可以重载下标操作符
    • 目的:以允许在对象上通过数组下标访问该数组成员的元素

    下标操作符必须重载两个版本

    • 常函数版本用于处理常量

    数组下标越界错误

    • 可以在重载函数中处理数组下标越界错误,或使用异常处理机制
    class Couple
    {
    public:
    	Couple(int a = 0,b = 0){_a[0] = a,_a[1] = b;}
        int& operator[](int index);
        const int& opertor[](int index) const;
    private:
        int _a[2];
    };
    int& Couple::operator[](int index)
    {
        if(index < 0 || index > 1)
            throw std::out_of_range("The index is out of range.");
        return _a[index];
    }
    const int& operator[](int index) const
    {
       if(index < 0 || index > 1)
            throw std::out_of_range("The index is out of range.");
        return _a[index]; 
    }
    int main()
    {
        Couple a(1,2),b(3,4);
        cin>>a[0]>>a[1];
        cout<<b[0]<<" "<<b[1];
        return 0;
    }
    

    4.赋值操作符重载

    赋值操作符重载的一般形式

    class Couple
    {
    public:
        Couple(int a = 0,int b = 0):_a(a),_b(b){}
        Couple(const Couple& c):_a(c._a),_b(c._b){}
        Couple& operator=(const Couple& c);
    private:
        int _a,_b;
    };
    Couple& Couple::operator=(const Couple& c)
    {
        if(*this == c)
            return *this;
        _a = c._a,_b = c._b;
        return *this;
    }
    int main()
    {
        Couple a(1,2),b(3,4);
        a = b;
        cout<<a<<endl;
        return 0;
    }
    

    复合赋值操作符重载

    class Couple
    {
    public:
        Couple(int a = 0,int b = 0):_a(a),_b(b){}
        Couple(const Couple& c):_a(c._a),_b(c._b){}
        Couple& operator+=(const Couple& c);
        Couple& operator*=(const Couple& k);
        Couple& operator*=(const int& k);
        void Print(){cout<<_a<<" "<<_b<<endl;}
    private:
        int _a,_b;
    };
    Couple& Couple::operator+=(const Couple& c)
    {
        _a += c._a,_b += c._b;
        return *this;
    }
    Couple& Couple::operator*=(const Couple& k)
    {
        _a *= k._a,_b *= k._b;
        return *this;
    }
    Couple& Couple::operator*=(const int& k)
    {
        _a *= k,_b *= k;
        return *this;
    }
    int main()
    {
        Couple a(1,2),b(3,4);
        a += b;
        a.Print();
        a *= 2;
        a.Print();
        return 0;
    }
    

    赋值构造与拷贝构造

    • 赋值也是构造

    • 拷贝、赋值与析构三位一体,一般同时出现

      --缺省赋值构造与拷贝构造为浅拷贝

      --如果对象没有指针成员,缺省行为即可满足要求,无需实现或重载这三个函数

      --如果对象有指针成员,一般需要重载这三个函数

    浅拷贝与深拷贝

    移动语义(C++11)

    5.流操作符重载

    为数偶类定义专用的流操作符

    class Couple
    {
    public:
        Couple(int a = 0, int b = 0):_a(a),_b(b){}
        //必须使用此格式,以与流的连续读写特性保持一致
        friend ostream& operator<<(ostream& os,const Couple& c);
        friend istream& operator>>(istream& is,Couple& c);
    private:
        int _a,_b;
    };
    //注意:此处实现的流输入输出格式不统一
    ostream& operator<<(ostream& os,const Couple& c)
    {
        os<<"("<<c._a<<","<<c._b<<"("<<endl;
        return os;
    }
    istream& operator>>(istream& is,Couple& c)
    {
        is>>c._a>>c._b;
        return is;
    }
    int main()
    {
        Couple a(1,2),b;
        cin>>b;
        cout<<a<<b<<endl;
        return 0;
    }
    

    6.操作符重载总结

    哪些操作符可以重载?

    • 不可重载操作符:“::” "?:" "." ".*" "sizeof" "#" "##" "typeid"
    • 其他操作符都可重载

    操作符重载原则

    • 只能使用已有的操作符,不能创建新的操作符
    • 操作符也是函数,重载遵循函数重载原则
    • 重载的操作符不能改变优先级与结合性,也不能改变操作数个数及语法结构
    • 重载的操作符不能改变其用于内部类型对象的含义,它只能和用户自定义类型的对象一起使用,或者用于用户自定义类型的对象和内部类型的对象混合使用
    • 重载的操作符在功能上应与原有功能一致,即保持一致的语义
  • 相关阅读:
    600+ 道 Java面试题及答案整理(2021最新版)
    Spring Boot + Web Socket 实现扫码登录,这种方式太香了!!
    小团队适合引入 Spring Cloud 微服务吗?
    Netty 通道怎么区分对应的用户?
    软件开发打败了 80 %的程序员
    一个最简单的消息队列,带你理解 RabbitMQ!
    厉害了,Netty 轻松实现文件上传!
    Netty 是如何解决 TCP 粘包拆包的?
    图解 Git,一目了然!
    面试官:谈谈分布式一致性机制,我一脸懵逼。。
  • 原文地址:https://www.cnblogs.com/bear-Zhao/p/13848191.html
Copyright © 2020-2023  润新知