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'<<'\n';
    }
    //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' << '\n';
    }
    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'<<'\n';
    }
    //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'<<'\n';
}

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++的基本类型

 

  

 

posted @ 2020-08-17 19:45  天子骄龙  阅读(898)  评论(0编辑  收藏  举报