C++学习之操作符重载

  1. 基本概念
    操作符重载就是一些具有特殊名称的函数,“operator操作符”,把已存在操作进行重新定义,针对自定义的类类型对象,完成自定义的运算功能.

  2. 双目操作符重载: L#R
    2.1 运算类的双目操作符:+ - …
    –》表达式结果是右值,不能对表达式结果再赋值
    –》左右操作数既可以是左值也可以是右值
    –》具体实现方式有两种:
    1)成员函数形式(左调右参)
    L#R的表达式可以被编译器处理为L.operator#®的成员函数调用形式,由该函数实现自定义的运算功能,其返回结果就是表达式的结果。
    2)全局函数形式(左右都参数)
    L#R的表达式也可以被编译器处理为operator#(L,R)的全局函数调用形式,由该函数实现自定义的运算功能,其返回结果就是表达式的结果
    注:可以使用friend关键字,将全局函数形式操作符重载函数,声明为类的友元,友元函数可以访问类中任何成员。

    2.2 赋值类的双目操作符:+= -= …
    –》表达式结果是左值,就是左操作数的自身
    –》左操作数必须是左值,右操作数左值或右值又可以
    –》具体实现方式有两种:
    1)成员函数形式
    L#R ==> L.operator#(R)
    2)全局函数形式
    L#R ==> operator#(L,R)

  3. 单目操作符重载:#O
    1.1 运算类单目操作符:-(负) ~(取反)
    –》表示结果是右值,不能对表达式结果再赋值
    –》操作数可以是左值也可以是右值
    –》具体实现方式有两种:
    1)成员函数形式
    #O ==> O.operator#()
    2)全局函数形式
    #O ==> operator#(O)

    1.2 自增减单目操作符:++ –
    1)前缀自增减
    –》表达式结果是左值,就是操作数自身
    –》操作数一定是左值
    –》两种实现方式:
    成员函数形式:#O ==> O.operator#()
    全局函数形式:#O ==> operator#(O)

    2)后缀自增减
    –》表达式结果是右值,是操作数自增减之前的数值
    –》操作数一定是左值
    –》两种实现方式:
    成员函数形式:O# ==> O.operator#(int/*哑元*/)
    全局函数形式:O# ==> operator#(O,int/*哑元*/)

  4. 输出(插入)和输入(提取)操作符重载:<< >>
    功能:实现自定义类型对象的直接输出或输入
    注:ostream和istream是标准库的类,不能直接修改,所以重载时只能选择全局函数形式.

    #include
    ostream//标准输出流类,cout是ostream类型的对象
    istream//标准输入流类,cin是istream类型的对象

    //输出操作符重载函数
    friend ostream& operator<<(ostream& os,const Right& r){

    return os;
    }
    //输入操作符重载函数
    friend istream& operator>>(istream& is,Right& r){

    return is;
    }

    //全局函数:operator<<(cout,a)
    cout << a << …;

    //全局函数:operator>>(cin,a)
    cin >> c >>…;

  5. 练习:实现一个3*3矩阵类,支持如下操作符重载
    + - += -= -(负) 前后++、-- <<
    * *=
    提示:
    class M33{
    public:
    private:
    int m_a[3][3];
    };

    1 2 3		9 8 7		10 10 10
    4 5 6	+	6 5 4 = 	10 10 10
    7 8 9		3 2 1		10 10 10
    
    1 2 3		9 8 7		-8 -6 -4
    4 5 6	+	6 5 4 = 	-2  0  2
    7 8 9		3 2 1		 4  6  8
    
    1 2 3		9 8 7		30  24  18
    4 5 6	*	6 5 4 = 	84  69  54
    7 8 9		3 2 1		138 114 90
    
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    class M33{
    public:
        M33(void){
            memset((void *)m_a, 0, sizeof(int)*3*3);
        }
        M33(int a[][3]){
            memcpy((void *)m_a, (void *)a, sizeof(int)*3*3);
        }
        //输出操作符重载:<<
        friend ostream& operator<<(ostream& os,const M33& m){
            for(int i=0;i<3;i++){
                for(int j=0;j<3;j++)
                    os << m.m_a[i][j] << ' ';
                cout << endl;
            }
            return os;
        }
        //+
        const M33 operator+(const M33& m) const{
            int a[3][3] = {0};
            for(int i=0;i<3;i++)
                for(int j=0;j<3;j++)
                    a[i][j]=m_a[i][j]+m.m_a[i][j];
            //M33 res(a);
            //return res;
            return a;
        }
        //-
        const M33 operator-(const M33& m) const{
            int a[3][3] = {0};
            for(int i=0;i<3;i++)
                for(int j=0;j<3;j++)
                    a[i][j]=m_a[i][j]-m.m_a[i][j];
            M33 res(a);
            return res;
        }
        //*
        const M33 operator*(const M33& m) const{
            int a[3][3] = {0};
            for(int i=0;i<3;i++)
                for(int j=0;j<3;j++)
                    for(int k=0;k<3;k++)
                    a[i][j]+=m_a[i][k]*m.m_a[k][j];
            M33 res(a);
            return res;
        }
        //+=
        //m1+=m2 ==> m1=m1+m2
        M33& operator+=(const M33& m){
            *this = *this + m;
            return *this;
        }
        //-= 
        M33& operator-=(const M33& m){
            *this = *this - m;
            return *this;
        }
        //*=
        M33& operator*=(const M33& m){
            *this = *this * m;
            return *this;
        }
        //-(负) 
        const M33 operator-(void)const{
            //M33 m;
            //return m - *this;
            return M33() - *this;
        }
        //前++,-- 
        M33& operator++(void){
            for(int i=0;i<3;i++)
                for(int j=0;j<3;j++)
                    ++m_a[i][j];
            return *this;
        }
        M33& operator--(void){
            for(int i=0;i<3;i++)
                for(int j=0;j<3;j++)
                    --m_a[i][j];
            return *this;
        }
        //后++,--
        const M33 operator++(int){
            M33 old = *this;
            ++(*this);
            return old;
        }
        const M33 operator--(int){
            M33 old = *this;
            --(*this);
            return old;
        }
    
    
    private:
        int m_a[3][3];
    };
    int main(void){
        int a1[3][3] = {1,2,3,4,5,6,7,8,9};
        int a2[3][3] = {9,8,7,6,5,4,3,2,1};
        M33 m1(a1);
        M33 m2(a2);
        cout << m1 << endl;
        cout << m2 << endl;
        cout << "m1+m2:" << endl;
        cout << m1+m2 << endl;//m1.operator+(m2)
        cout << "m1-m2:" << endl;
        cout << m1-m2 << endl;//m1.operator-(m2)
        cout << "m1*m2:" << endl;
        cout << m1*m2 << endl;//m1.operator*(m2)
        cout << "m1+=m2:" << endl;
        cout << (m1+=m2) << endl;
        cout << m1 << endl;
        cout << "m1-=m2:" << endl;
        cout << (m1-=m2) << endl;
        cout << m1 << endl;
        cout << "m1*=m2:" << endl;
        cout << (m1*=m2) << endl;
        cout << m1 << endl;
    
        cout << "-m2:" << endl;
        cout << -m2 << endl;
        
        cout << "++m2:" << endl;
        cout << ++m2 << endl;
        cout << m2 << endl;
        cout << "--m2:" << endl;
        cout << --m2 << endl;
        cout << m2 << endl;
        
        cout << "m2++:" << endl;
        cout << m2++ << endl;
        cout << m2 << endl;
        cout << "m2--:" << endl;
        cout << m2-- << endl;
        cout << m2 << endl;
    
        return 0;
    }
    
  6. 下标操作符重载:[]
    功能:实现自定义类型对象能够像数组一样使用
    注:非const对象返回左值,常对象返回右值
    string str = “…”
    //str.operator == ‘A’
    str[i] = ‘A’;

    const string str = “…”
    //str.operator == ‘A’
    str[i] = ‘A’;//error

    #include <iostream>
    using namespace std;
    //模拟容器类:里面可以存放若干个int数据
    class Array{
    public:
        Array(size_t size){
            m_arr = new int[size];
        }
        ~Array(void){
            delete[] m_arr;
        }
        //下标操作符重载:[]
        int& operator[](size_t i){
            cout << "匹配非const对象" << endl;
            return m_arr[i];
        }
        const int& operator[](size_t i)const{
            cout << "匹配const对象" << endl;
            return m_arr[i];
        }
    private:
        int* m_arr;
    };
    int main(void){
        Array arr(10);
        arr[0] = 123;//arr.operator[](0) = 123
        cout << arr[0] << endl;//123
    
        const Array& arr2 = arr;
        //arr2[0] = 321;//应该error
        cout << arr2[0] << endl;//123
    
        return 0;
    }
    
  7. 函数操作符: ()
    功能:实现让自定义类型的对象像函数一样去使用//仿函数
    注:对参数个数、类型和返回值没有任何限制
    A a(…);
    a(100,1.23);//a.operator()(100,1.23)

    #include <iostream>
    using namespace std;
    class Func{
    public:
        int operator()(int i,int j){
            return i * j;
        }
        int operator()(int i){
            return i * i;
        }
    };
    int main(void){
        Func func;//仿函数
        //func.operator()(100,200)
        cout << func(100,200) << endl;//20000
        //func.operator()(100)
        cout << func(100) << endl;//10000
    
        return 0;
    }
    
  8. new和delete操作符重载
    static void* operator new(size_t size){…}
    static void operator delete(void* p){…}

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    class A{
    public:
        A(void){
            cout << "A的构造函数" << endl;
        }
        ~A(void){
            cout << "A的析构函数" << endl;
        }
        static void* operator new(size_t size){
            cout << "分配内存" << endl;
            void* pv = malloc(size);
            return pv;
        }
        static void operator delete(void* pv){
            cout << "释放内存" << endl;
            free(pv);
        }
    };
    int main(void){
        //1)A* pa = (A*)A::operator new(sizeof(A))
        //2)pa->构造函数
        A* pa = new A;
        
        //1)pa->析构函数
        //2)A::operator delete(pa)
        delete pa;
        pa = NULL;
        return 0;
    
    }
    
  9. 操作符重载的限制
    1)不是所有的操作符都能重载,不能重载的操作符如下:
    作用域限定操作符::
    直接成员访问操作符.
    直接成员指针解引用操作符.*
    条件操作符? :
    字节长度操作符sizeof sizeof里的表达式不会被计算,如sizeof(a=b),执行完之后a并不会等于b
    类型信息操作符typeid
     
    2)如果一个操作符所有的操作数都是基本类型,则无法重载
     
    3)操作符重载不会改变编译器预定义的优先级
     
    4)操作符重载不会改变操作符的个数
     
    5)无法通过操作符重载发明新的符号,如operator@,本身@就不是操作符,所以不可重载
     
    6)只能使用成员函数形式重载操作符
    = [] () ->

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值