• C++ Primer 第十四章 重载操作符与转换


    14.1 重载操作符的定义

        操作符(+ ,- , * , / , = , < , >)可以被内置类型使用,比如两个整数相加或相减,两个字符串相加,两个数组比较大小等等。自定义类默认是不能使用大多数操作符的。自定义类是复合类型,相加或想减或比较大小并没有相应的规则匹配:两个类相加等于什么? 两个类如何确定谁大谁小?  C++允许我们通过重载运算符的技术让自定义对象支持这些操作。我们可以定义重载规则。

        操作符重载语法很简单: 关键字 operator 后接操作符 比如 operator+

        可以重载的操作符:

       

        不能重载的操作符:

    :: . .* ?  :
    sizeof typeid new delete
    static_cast dynamic_cast const_cast reinterpret_cast

       

        重载操作符可以定义成类成员函数,也可以定义成非成员函数

    class myclass
    {
       public:
          myclass() : age(0){};

          // 成员函数定义

          myclass operator+(const myclass &obj) const
          {
               myclass cls;
               cls.age = age + obj.age;
               return cls;
           };

       
           int age;
    }

    // 等价的非成员函数定义

    myclass operator+(const myclass &obj1, const myclass &obj2)
    {
        myclass cls;
        cls.age = obj1.age + obj2.age;
        return cls;
    }

      

        成员函数定义看起来少了一个参数,实际上语法将this限定为第一个操作数。大部分操作符允许定义为成员或非成员函数,具体如何定义看个人喜好。


        + 有些操作符只能定义为成员,如果定义成非成员会产生编译错误 赋值= 下标[] 调用() 箭头访问-> 都不允许定义成非成员函数。
        + 有些操作符只能定义为非成员,如 输入 << 输出 >> 操作符
        + 改变自身状态的建议定义为成员函数,例如 自增++ 自减-- 解引 复合操作+= -=
        + 对称操作符建议定义为非成员函数,例如加减 + - 比较 < == >
        + 成员函数中可以使用 this 而非成员函数中无法使用,因为函数不属于任何对象。

        重载操作符至少要包含一个类类型操作数

        myclass operator+(myclass *obj1, const myclass *obj2) // 操作数至少要包含一个类类型,防止用户修改内置类型的操作符,如果用户定义 int operator+(int a,int b) 意味着用户要修改int类型的加法操作符。 

        输入操作符:

    &ostream operator<<(ostream &temp, const myclass &obj) // 第二个形参一般都作const限定因为它只做读取操作    
    {
        temp << obj.size;
        return temp;
    }   

        输出操作符:

    &istream operator>>(istream &temp, myclass &obj) // 第二个形参不能const限定,因为需要输入内容到该参数中
    {
        tmp >> obj.size;
        return temp;
    }
       

        输入输出操作符返回都必须是引用,且第一个形参也是引用,前面章节中已说明 IO对象无法复制或者赋值。
        这两个操作符只能定义成非成员函数,原因在于第一形参必须是IO对象引用,而定义为成员函数时第一个参数被省略且被限定为 this 所以只能定义成非成员函数。

      

        算数运算符:

    myclass operator+(const myclass &obj1, const myclass &obj2)
    {
        myclass cls;
        cls.age = obj1.age + obj2.age;
        return cls;
    }

    myclass operator-(const myclass &obj1, const myclass &obj2)
    {
        myclass cls;
        cls.age = obj1.age - obj2.age;
        return cls;
    }

    bool operator==(const myclass &obj1, const myclass &obj2)
    {
        return obj1.age == obj2.age;
    }

    bool operator>(const myclass &obj1, const myclass &obj2)
    {
        return obj1.age > obj2.age;
    }

        赋值=操作符:

    myclass& operator=(const myclass &obj)  // 赋值符左操作数是this 指向对象(当前类对象),赋值符号右操作数是形参obj 返回值必须是*this的引用
    {
        age = obj.age; 
        return *this
    };


        下标操作符:

    string operator[] (const size_t index) // 返回左值(常量) 下标操作只读
    stringoperator[] (const size_t index) // 返回左值(引用) 下标操作可读可写

    下标操作可实现const重载 
    stringoperator[] (const size_t index) // 下标操作可读可写
    const stringoperator[] (const size_t index) const // 下标操作只读

    调用规则是 const对象调用const版,非const调用非const版
    myclass a ;
    a[1] ; // 调用非const版

    const myclass b ;
    b[1] ; // 调用const版

        解引操作符:

    class cls
    {
        public:
            void show(int p){cout << p << endl;};
    }

    class myclass
    {
        public:
            myclass:sp(p) (cls *p)
            cls &operator*(){return *sp;}; // 解引返回具体类
            cls *operator->(){return sp;}; // 箭头返回类指针,实际使用时返回的指针会立刻再做系统的箭头操作

            const cls &operator*() const {return *sp;}; // const重载版本
            const cls *operator->() const {return sp;}; // const重载版本
        private:
            cls *sp;
    }

    cls a;

    myclass t(&a) ;

    cls b = *t ; // 调用解引操作符,返回cls类对象

    t->show(3) ; // 调用箭头操作符,调用cls对象的show()方法

    此时t是对象而不是指针,如果t是指针,则会调用系统解引和箭头操作:

    cls *j = &t;

    *j ; // 返回 myclass对象

    j->show(3) ; // 调用myclass对象的show方法,本例中myclass没有定义方法,运行时报错

        自增操作符:

    class myclass
    {
        public:
            int ls[4];
            int *cur;
            myclass:ls{2,3,1,5},cur(ls){};
            myclass &operator++(){ cur ++; return *this;}; // ++myclass重载,返回引用或对象
            myclass operator++(int){ myclass tmp(*this); cur ++; return tmp;}; // myclass++重载,只能返回对象(不允许返回局部对象的引用)
    }

    myclass++重载多了形参int,只起到标识作用。
    使用和内置类自增没审美区别,自减和自增类似。

     

        调用操作符:

    class myclass
    {
        public:
            int operator() (int i){ return i + 2;};
    }

    定义了调用操作符的类对象叫做 函数对象 ,因为他们的对象行为类似函数
    myclass obj;
    int j = obj(5) ; // 使用调用操作符重载函数 j = 7

        转换操作符:

    class myclass
    {
        public:
            operator int() const (){ return a;};
        private:
            int a;
    }

        在下列情况下函数执行:

        1. 表达式中  1 + obj; 2 < obj;

        2. 条件中 if(obj)  先转换成int 在转成bool

        3. 传参或返回值时

  • 相关阅读:
    机器学习——线性回归
    系统课程
    C++——数据结构之链表
    PHP检测json格式数据
    如何搭建git服务器
    ucenter通信实现同步登录、同步退出(详细)
    获取ip地址
    JQuery对象与DOM对象的区别与转换
    php导出数据到csv文件
    [转载]php中sleep,flush,ob_flush函数介绍
  • 原文地址:https://www.cnblogs.com/kingcat/p/2503705.html
Copyright © 2020-2023  润新知