运算符重载复习

0.引言

1.使用 operator 关键字引入重载函数

  • 函数参数个数与运算操作数个数相同,至少一个为类类型(不能全部都是内建类型)

    #include<iostream>
    #include<vector>
    #include<string>
    struct Str
    {
      int val;
    };
    //均为内建类型,非法
    auto operator +(int x, double y){
    
    }
    
    int main(){
      Str x;
      Str y;
      x + y;//合法
    }
    
  • 除 operator() 外其它运算符不能有缺省参数(这里的operator()是重载小括号"()"的意思)

    struct Str
    {
      int val = 3;
    
      //operator() 可以带缺省参数 
      //典型的运算符重载
      auto operator () (int y = 3){
        return val + y;
      }
    
    };
    
  • 可以选择实现为成员函数与非成员函数

    • 通常来说,实现为成员函数会以 *this 作为第一个操作数(注意 == 与 <=> 的重载)
    #include<iostream>
    #include<vector>
    #include<string>
    struct Str
    {
      int val = 3;
    
      //operator() 可以带缺省参数 
      //典型的运算符重载
      auto operator () (int y = 3){
        return val + y;
      }
    
      auto operator +(Str x){
        Str z;
        z.val = val + x.val;
        return z;
      }
    
    };
    
    int main(){
      Str x;
      Str y;
      Str z = x + y;//x-->this, y为输入的参数
      ----
      std::cout<< x(5) <<std::endl;//8
      std::cout<< x() <<std::endl;//6
    }
    

2.根据重载特性,可以将运算符进一步划分

  • 可重载且必须实现为成员函数的运算符( =,[],(),-> 与转型运算符)(可重载的基本都可以重载为成员函数,但这几个必须重载为成员函数)
  • 可重载且可以实现为非成员函数的运算符
  • 可重载但不建议重载的运算符( &&, ||, 逗号运算符)
    • C++17 中规定了相应的求值顺序但没有方式实现短路逻辑
  • 不可重载的运算符(如 ? :运算符)

3.运算符重载

  • 对称运算符通常定义为非成员函数以支持首个操作数的类型转换

    #include<iostream>
    #include<vector>
    #include<string>
    
    struct Str
    {
      Str(int x)
        : val(x)
        {}
      // 全局域的函数
      // 类内定义友元函数的典型应用
      friend auto operator +(Str input1, Str input2){
        //使用友元来更改权限
        return Str(input1.val + input2.val);
      }
    private:
      int val;
    };
    
    int main(){
      Str x = 3;
      Str z = 4 + x;//合法
    }
    
  • 移位运算符一定要定义为非成员函数,因为其首个操作数类型为流类型

       //std::cout<<std::enl;就是重载了移位运算符
      //ostream输出流
      friend auto& operator << (std::ostream& ostr, Str input)
      {
        ostr << input.val;
        return ostr;//为什么要返回ostr
        - 为了支持:std::cout<< x << z;这种连续操作
        - 如果不返回,就只能输出一次!
      }
    
    
  • 赋值运算符也可以接收一般参数

    
      // 第一参数为*this
      // 拷贝赋值运算符
      Str& operator=(const Str& input){
        val = input.val;
        return *this;
      }
      // = 是二元操作符
      Str& operator=(const std::string& input){
        val = static_cast<int>input.size();
        return *this;
      }
    
    
  • operator [ ] 通常返回引用–举例:使用重载[ ]模拟数组的访问操作!

        - 返回引用才能支持写操作,否则只支持读操作!
      int& operator[](int id)
      {
        return val;
      }
    
      //重载一个const属性的操作
      int operator[](int id)
      {
        return val;
      }
    
  • 自增、自减运算符的前缀、后缀重载方法

    
      //我们需要一种办法去判断是前缀自增还是后缀自增
      Str& operator++ ()//没有参数:前缀自增(自减同理)
      {
        ++val;
        return *this;
        - 为什么要返回*this
        - 为了能实现类似++(++x)这样的操作
      }
      //有参数:后缀自增(自减同理),input变量没有实际意义
      Str operator++ (int)
      {
        - 这也是平时代码中尽可能使用前缀自增的原因
        Str tmp(*this);//拷贝构造,可能很耗时
        ++val;
        return tmp;//返回的是副本,然后再++
      }
    
  • 使用函数调用运算符构造可调用对象

    #include<iostream>
    #include<vector>
    #include<string>
    
    struct Str
    {
      Str(int p)
        :ptr(p)
      {
      }
      //operator()函数调用运算符:ORB-SLAM2的特征点提取就是用的这个
      int operator() ()
      {
        return val;
      }
    
      int operator() (int x, int y, int z)
      {
        return val+x+y+z;
      }
    private:
      int val;
    };
    
    int main(){
      Str obj(100);
      std::cout<< obj() <<std::endl;
      std::cout<< obj(1,2,3) <<std::endl;
    }
    

    ORB-SLAM2中的函数调用操作符重载:

    - 声明
        void operator()( cv::InputArray image, cv::InputArray mask,
                          std::vector<cv::KeyPoint>& keypoints,
                          cv::OutputArray descriptors);
    
    - 调用
      (*mpORBextractorLeft)(im,cv::Mat(),mvKeys,mDescriptors);
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值