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, const 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. 传参或返回值时

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值