• C++操作符重载(operator)


    为什么使用赋值运算符重载函数?

    对于系统的所有操作符,一般情况下,只支持基本数据类型和标准库中提供的class,对于用户自己定义的class或struct的对象,如果想支持基本操作,比如比较大小,判断是否相等,等等,则需要用户自己来定义关于这个操作符的具体实现。

    比如,判断两个人是否一样大,我们默认的规则是按照其年龄来比较,所以,在设计person 这个class的时候,我们需要考虑操作符==,而且,根据刚才的分析,比较的依据应该是age。那么为什么叫重载呢?这是因为,在编译器实现的时候,已经为我们提供了这个操作符的基本数据类型实现版本,但是现在他的操作数变成了用户定义的数据类型class,所以,需要用户自己来提供该参数版本的实现

    双目操作符重载

    赋值类双目操作符重载

    成员函数方式

    #include <iostream>
    //复数类
    class Complex{
    public:
        Complex(int r=0,int i=0):m_r(r),m_i(i){    }    
        void print(void)const{
        std::cout<<m_r<<'+'<<m_i<<'i'<<'
    ';
        }
        //c1+=c2==>c1.operator+=(c2)  c1就是自身 
        Complex& operator+=(const Complex& c ){
            m_r+=c.m_r;
            m_i+=c.m_i;        
            return *this;
        }
            
    private:
        int m_r; //实部
        int m_i; //虚部 
    }; 
    
    int main()                                                                                                                                   
    {
        Complex c1(10,20);
        Complex c2(5,8);
        Complex c3 =c1+=c2;
        c3.print();
        
        
        return 0;
    }

    全局函数方式

    #include <iostream>
    //复数类
    class Complex {
    public:
        Complex(int r = 0, int i = 0) :m_r(r), m_i(i) {    }
        void print(void)const {
            std::cout << m_r << '+' << m_i << 'i' << '
    ';
        }
        friend Complex& operator-=(Complex& l, const Complex& r);
    private:
        int m_r; //实部
        int m_i; //虚部 
    };
    
    //c1-=c2==>operator-=(c1,c2)
    Complex& operator-=(Complex& l, const Complex& r) {
        l.m_r -= r.m_r;
        l.m_i -= r.m_i;
        return l;
    }
    
    
    int main()
    {
        Complex c1(10, 20);
        Complex c2(5, 8);
        c1 -= c2;
        c1.print();
    
    
        return 0;
    }

    计算类双目操作符重载

    成员函数方式

    L#R的表达式可以被编译器处理为“L.operator#(R)”成员函数调用形式,该函数的返回值就是表达式的结果

    比如:c1+c2      c1.operator+(c2)

    #include <iostream>
    //复数类
    class Complex{
    public:
        Complex(int r=0,int i=0):m_r(r),m_i(i){    }    
        void print(void)const{
        std::cout<<m_r<<'+'<<m_i<<'i'<<'
    ';
        }
        //c1+c2==>c1.operator+(c2)  c1就是自身
        const Complex operator+(const Complex& c) const{  //+操作符重载
        //第一个const: 保证返回值是右值
        //第二个const:支持常量型右操作数 
        //第三个const: 支持常量型左操作数
        Complex res(m_r+c.m_r,m_i+c.m_i);
        return res;
        }
            
    private:
        int m_r; //实部
        int m_i; //虚部 
    }; 
    
    int main()                                                                                                                                   
    {
        Complex c1(10,20);
        Complex c2(5,8);
        c1.print();
        c2.print();
        Complex c3=c1+c2;//调用+重载函数
        c3.print();
        
        
        
        return 0;
    }

    全局函数方式 

    L#R的表达式可以被编译器处理为“operator#(L,R)”全局函数调用形式,该函数的返回值就是表达式的结果 

    #include <iostream>
    //复数类
    class Complex{
    public:
    Complex(int r=0,int i=0):m_r(r),m_i(i){ }
    void print(void)const{
    std::cout<<m_r<<'+'<<m_i<<'i'<<' ';
    }

    private:
    int m_r; //实部
    int m_i; //虚部
    //友元函数:把一个全局函数声明为友元函数, 友元函数可以访问类中任何成员
    friend const Complex operator-(const Complex& l,const Complex& r);
    };

    //重载- :全局方式
    //c2-c1==>operator-(c2,c1)
    const Complex operator-(const Complex& l,const Complex& r){
    Complex res(l.m_r-r.m_r,l.m_i-r.m_i);
    return res;
    }

    int main()
    {
    Complex c1(10,20);
    Complex c2(5,8);
    c1.print();
    c2.print();
    Complex c3=c1-c2;
    c3.print();


    return 0;
    }

    单目操作符重载 

    计算单目操作符

    比如:-(负)   ~(位反)

    成员函数实现

    #include <iostream>
    
    class Integer {
    public:
        Integer(int i = 0) :m_i(i) { }
        void print(void)const {
            std::cout << m_i << std::endl;
        }
    
        //Integer j = -i ==>i.operator-()
        const Integer operator-(void)const {
            //没有形参:操作数就是自身
            Integer res(-m_i);
            return res;
       }
    
    private:
        int m_i;
    };
    
    
    // operator
    
    int main()
    {
        Integer i(100);
        Integer j = -i;
        j.print();
    
        return 0;
    }

    全局函数实现

    #include <iostream>
    
    class Integer {
    public:
        Integer(int i = 0) :m_i(i) { }
        void print(void)const {
            std::cout << m_i << std::endl;
        }
    
        //Integer j = -i ==>i.operator-()
        friend const Integer operator~(const Integer& i);
    private:
        int m_i;
    };
    
    
    const Integer operator~(const Integer& i) {
        Integer res(i.m_i* i.m_i);
        return res;
    }
    
    int main()
    {
        Integer i(100);
        Integer j = ~i;
        j.print();
    
        return 0;
    }

    自增减单目操作符

    比如:++    --

    #include <iostream>
    
    class Integer {
    public:
        Integer(int i = 0) :m_i(i) { }
        void print(void)const {
            std::cout << m_i << std::endl;
        }
    
        /*
        左值:有特定的地址,其值可以修改
        a++ 不可以作为左值;++a 可以作为左值
        a++的意思是先复制一份临时数据出来参与周边环境的运算,再自加变量a,可见a++用来参与运算的是一份复制出来的临时数据,这个数据是临时存在而没有固定地址的,不是一个真正的变量,所以只能是右值
        ++a的意思是先自加变量a,再将变量放到周边环境参与运算,那么++a用来参与运算的是有具体地址的变量,所以++a是可以作为左值使用的
        哑元:一个函数的参数 只有类型 没有名字 则这个参数称之为哑元
        后缀操作符重载会多一个哑元参数,用来与前缀操作符重载的区分
        */
    
        //前++   成员函数形式
         Integer& operator++(void) {
            //没有形参:操作数就是自身
             ++m_i;
            return *this;
        }
         friend Integer& operator--(Integer& i);
    
         //后++  成员函数形式
         const Integer operator++(int) {
             //参数:哑元参数
             Integer old = *this;
             ++m_i;
             return old;
         }
    
         friend const Integer operator--(Integer& i,int);
         
    
    private:
        int m_i;
    };
    
    //前--  全局函数形式
    Integer& operator--(Integer& i) {
        --i.m_i;
        return i;
    }
    
    //后--   全局函数形式
    const Integer operator--(Integer& i, int) {
        //参数:哑元参数
        Integer old = i;
        --i.m_i;
        return old;
    }
    
    
    int main()
    {
        Integer i(100);
        Integer j=++i;
        j.print();
    
        return 0;
    }

    输入输出操作符重载(<<   >>) 

    #include<iostream>
    
    class Complex {
    public:
        Complex(int r,int i):m_r(r),m_i(i){}
        
        //<< 操作符重载函数
        // cout<<c1 ==>operator<<(cout,c1)
        friend std::ostream& operator<<(std::ostream& os, const Complex& c) {
            os << c.m_r << '+' << c.m_i << 'i';
            return os;
        }
    
        //>> 操作符重载函数
        // cout<<c1 ==>operator>>(cout,c1)
        friend std::istream& operator>>(std::istream& is, Complex& c) {
            std::cout << "输入实部:";
            is >> c.m_r;
            std::cout << "输入虚部:";
            is >> c.m_i;
            return is;
        }
    
    private:
        int m_r;//实部
        int m_i;//虚部
    };
    
    
    int main()
    {
        Complex c1(10, 20);
        Complex c2(1, 2);
        
        std::cout << c1 << std::endl;  //"10+20i"
        std::cin >> c2;
        std::cout << c2 << std::endl;
    
        return 0;
    }

    可见,当用一个非类A的值(如上面的int型值)为类A的对象赋值时:

    ①如果匹配的构造函数和赋值运算符重载函数同时存在,会调用赋值运算符重载函数

    ②如果只有匹配的构造函数存在,就会调用这个构造函数

     重载运算符的规则:

    重载运算符的函数不能有默认的参数:不然就改变了运算符参数的个数

    重载运算符的函数参数至少有一个是本类的对象或引用,不能全部都是C++的基本类型

      

  • 相关阅读:
    如何解决WEB应用中文乱码问题
    js获取指定格式的时间字符串
    js 实现 Base64 编码的相互转换
    Sql Server 与 MySql 在使用 update inner join 时的区别
    VMware12创建新的虚拟机及设置硬件环境
    Sql Server 中使用日期遍历
    Linux 添加定时任务,crontab -e 命令与直接编辑 /etc/crontab 文件
    mysql 中 max_allowed_packet 查询和修改
    eclipse编译项目:Java @Override 注解报错的解决方法
    eclipse启动项目报错:java.lang.ClassNotFoundException: ContextLoaderListener
  • 原文地址:https://www.cnblogs.com/liming19680104/p/13519601.html
Copyright © 2020-2023  润新知