【CPP】运算符的重载

1- Operators in OpenCV

Function overloading

在这里插入图片描述

函数有相同的函数名,但是输入的参数不同,则可以分别定义不同情况的函数,而不需要反复定义新的函数名

  • More convenient to code as follows
    在这里插入图片描述

Operators for cv::Mat

matexample.cpp

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;

int main()
{
    float a[6]={1.0f, 1.0f, 1.0f, 2.0f, 2.0f, 2.0f};
    float b[6]={1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
    cv::Mat A(2, 3, CV_32FC1, a);
    cv::Mat B(3, 2, CV_32FC1, b);

    cv::Mat C = A * B;

    cout << "Matrix C = " << endl 
        << C << endl;
    return 0;
}

两个运算符被重载了:*<<

CMakeList.cpp

cmake_minimum_required(VERSION 3.1)
set (CMAKE_CXX_STANDARD 11)

project(matexample)

find_package(OpenCV REQUIRED)
message(STATUS "OpenCV library status:")
message(STATUS "    config: ${OpenCV_DIR}")
message(STATUS "    version: ${OpenCV_VERSION}")
message(STATUS "    libraries: ${OpenCV_LIBS}")
message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")

include_directories( ${OpenCV_INCLUDE_DIRS} )

# Declare the executable target built from your sources
add_executable(matexample matexample.cpp)

# Link your application with OpenCV libraries
target_link_libraries(matexample PRIVATE ${OpenCV_LIBS})

brew install openCV
cmake ..
make
Matrix C = 
[9, 12;
 18, 24]

Operator Overloading

  • Customizes the C++ operators for operands of user-defined types
  • Overloaded operators are functions with special function names

在这里插入图片描述

string demo.cpp

#include <iostream>
#include <string>

int main()
{
    std::string s("Hello ");
    s += "C";
    s.operator+=(" and CPP!");

    std::cout << s << std::endl;
    return 0;
}
Hello C and CPP!

2- Operator Overloading

Operator Overloading

  • Implementation of operator+() and operator+=()

A+B操作:this + t
A += B 运算:this += t

Example1

time.hpp

#pragma once
#include <iostream>

class MyTime
{
    int hours;
    int minutes;
  public:
    MyTime(): hours(0), minutes(0){}
    MyTime(int h, int m): hours(h), minutes(m){}

    MyTime operator+(const MyTime & t) const
    {
        MyTime sum;
        sum.minutes = this->minutes + t.minutes;
        sum.hours = this->hours + t.hours;

        sum.hours +=  sum.minutes / 60;
        sum.minutes %= 60;
        
        return sum;
    }
    MyTime & operator+=(const MyTime & t) 
    {
        this->minutes += t.minutes;
        this->hours += t.hours;

        this->hours +=  this->minutes / 60;
        this->minutes %= 60;
        
        return *this;
    }
    std::string getTime() const
    {
        return std::to_string(this->hours) + " hours and " 
                + std::to_string(this->minutes) + " minutes.";
    }
};

main.cpp

#include <iostream>
#include "time.hpp"

using namespace std;

int main()
{
    MyTime t1(2, 40);
    MyTime t2(1, 20);
    std::cout << (t1 + t2).getTime() << std::endl;

    t1 += t2; //operator
    t1.operator+=(t2); //function

    std::cout << t1.getTime() << endl;

    return 0;
}


4 hours and 0 minutes.
5 hours and 20 minutes.
  • If one operand is not MyTime, and is an int
MyTime t1(2, 40);
MyTime t2 = t1 + 20;
  • The function can be :
    MyTime operator+(int m) const
    {
        MyTime sum;
        sum.minutes = this->minutes + m;
        sum.hours = this->hours;
        sum.hours +=  sum.minutes / 60;
        sum.minutes %= 60;
        return sum;
    }
  • We can even support the following operation to be more user friendly
MyTime t1(2, 40);
MyTime t2 = t1 + "one hour";
    MyTime operator+(const std::string str) const
    {
        MyTime sum = *this;
        if(str=="one hour")
            sum.hours = this->hours + 1;
        else
            std::cerr<< "Only \"one hour\" is supported." << std::endl;
        return sum;
    }

Example 2

time.hpp

#pragma once
#include <iostream>

class MyTime
{
    int hours;
    int minutes;
  public:
    MyTime(): hours(0), minutes(0){}
    MyTime(int h, int m): hours(h), minutes(m){}

    MyTime operator+(const MyTime & t) const
    {
        MyTime sum;
        sum.minutes = this->minutes + t.minutes;
        sum.hours = this->hours + t.hours;

        sum.hours +=  sum.minutes / 60;
        sum.minutes %= 60;
        
        return sum;
    }
    MyTime & operator+=(const MyTime & t) 
    {
        this->minutes += t.minutes;
        this->hours += t.hours;

        this->hours +=  this->minutes / 60;
        this->minutes %= 60;
        
        return *this;
    }

    MyTime operator+(int m) const
    {
        MyTime sum;
        sum.minutes = this->minutes + m;
        sum.hours = this->hours;
        sum.hours +=  sum.minutes / 60;
        sum.minutes %= 60;
        return sum;
    }
    MyTime & operator+=(int m) 
    {
        this->minutes += m;
        this->hours +=  this->minutes / 60;
        this->minutes %= 60;
        return *this;
    }

    MyTime operator+(const std::string str) const
    {
        MyTime sum = *this;
        if(str=="one hour")
            sum.hours = this->hours + 1;
        else
            std::cerr<< "Only \"one hour\" is supported." << std::endl;
        return sum;
    }
    
    std::string getTime() const
    {
        return std::to_string(this->hours) + " hours and " 
                + std::to_string(this->minutes) + " minutes.";
    }
};

mai.cpp

#include <iostream>
#include "time.hpp"

using namespace std;

int main()
{
    MyTime t1(2, 40);
    std::cout << (t1 + 30).getTime() << std::endl;

    t1 += 30; //operator
    t1.operator+=(30); //function

    std::cout << t1.getTime() << endl;

    std::cout << (t1 + "one hour").getTime() << std::endl;
    std::cout << (t1 + "two hour").getTime() << std::endl;

    return 0;
}


3 hours and 10 minutes.
3 hours and 40 minutes.
4 hours and 40 minutes.
Only "one hour" is supported.
3 hours and 40 minutes.
  • Overloaded operators is more user-friendly than functions
  • But, wait…
t1 + 20;  // operator
t1.operator+(20);  // equivalent function invoking
  • How about the expression
20 + t1;

3-friend Functions

friend functions

友元函数

  • If we want that operator + can support (int + MyTime)
MyTime t1(2, 40);
20 + t1;
  • Let a friend function to help
  • Friend funtions

(1) Declare in a class body
(2) Granted class access to members (including private members)
(3) But not members

  • Again, friend functions are members! They just declared in the class body
class MyTime
{
  public:
    friend MyTime operator+(int m, const MyTime & t)
    {
        return t + m;
    }
};
  • A friend function is defined out of the class
  • No MyTime:: before its function name
class MyTime
{
  public:
    friend MyTime operator+(int m, const MyTime & t);
};
MyTime operator+(int m, const MyTime & t)
{
    return t + m;
}
  • Operator << can also be overloaded
  • but in (cout << t1;) , the first operand is std::ostream, not MyTime
  • To modify the definition of std::ostream ? NO!
  • Use a friend function
    friend std::ostream & operator<<(std::ostream & os, const MyTime & t)
    {
        std::string str = std::to_string(t.hours) + " hours and " 
                        + std::to_string(t.minutes) + " minutes.";
        os << str;
        return os;
    }
    friend std::istream & operator>>(std::istream & is, MyTime & t)
    {
        is >> t.hours >> t.minutes;
        t.hours +=  t.minutes / 60;
        t.minutes %= 60;
        return is;
    }
  • return 返回值一定要是std::i/ostream & 类型,否则无法链式输出,比如修改friend int operator << (...) {...return o}
std::cout << t1 << std::endl;  =>  0 << std::endl;

无法链式调用

Example3

time.hpp

#pragma once
#include <iostream>

class MyTime
{
    int hours;
    int minutes;
  public:
    MyTime(): hours(0), minutes(0){}
    MyTime(int h, int m): hours(h), minutes(m){}

    MyTime operator+(const MyTime & t) const
    {
        MyTime sum;
        sum.minutes = this->minutes + t.minutes;
        sum.hours = this->hours + t.hours;

        sum.hours +=  sum.minutes / 60;
        sum.minutes %= 60;
        
        return sum;
    }
    MyTime & operator+=(const MyTime & t) 
    {
        this->minutes += t.minutes;
        this->hours += t.hours;

        this->hours +=  this->minutes / 60;
        this->minutes %= 60;
        
        return *this;
    }

    MyTime operator+(int m) const
    {
        MyTime sum;
        sum.minutes = this->minutes + m;
        sum.hours = this->hours;
        sum.hours +=  sum.minutes / 60;
        sum.minutes %= 60;
        return sum;
    }

    friend MyTime operator+(int m, const MyTime & t)
    {
        return t + m;
    }

    std::string getTime() const
    {
        return std::to_string(this->hours) + " hours and " 
                + std::to_string(this->minutes) + " minutes.";
    }

    friend std::ostream & operator<<(std::ostream & os, const MyTime & t)
    {
        std::string str = std::to_string(t.hours) + " hours and " 
                        + std::to_string(t.minutes) + " minutes.";
        os << str;
        return os;
    }
    friend std::istream & operator>>(std::istream & is, MyTime & t)
    {
        is >> t.hours >> t.minutes;
        t.hours +=  t.minutes / 60;
        t.minutes %= 60;
        return is;
    }
};

main.cpp

#include <iostream>
#include "time.hpp"

using namespace std;

int main()
{
    MyTime t1(2, 40);
    std::cout << (30 + t1).getTime() << std::endl;

    std::cout << t1 << std::endl;
    std::cout << "Please input two integers:" << std::endl;
    std::cin >> t1;
    std::cout << t1 << std::endl;

    return 0;
}


3 hours and 10 minutes.
2 hours and 40 minutes.
Please input two integers:
3 80
4 hours and 20 minutes.

4- User Defined Type Conversion

Operator type()

  • Overloaded type conversion: convert the current type to another
    //implicit conversion
    operator int() const
    {
        std::cout << "operator int()" << std::endl;
        return this->hours * 60 + this->minutes;
    }
    //explicit conversion
    explicit operator float() const
    {
        std::cout << "explicit operator float()" << std::endl;
        return float(this->hours * 60 + this->minutes);
    }
MyTime t1(1, 20);
int minutes = t1;   // implicit conversion
float f = float(t1);  // explicit  conversion

希望将MyTime转换成一个整数,operator int()
加了explicit: 转换必须是显式的,不能隐式的转换

  • 如果:
MyTime t1(1, 20);
int minutes = t1;   // implicit conversion
float f = t1;  // explicit  conversion

这样不会报错,因为自动先调用 operator int() 转换成一个整数,再强制转换成float类型

Converting Constructor

  • Convert another type to the current
    MyTime(int m): hours(0), minutes(m)
    {
        std::cout << "Constructor MyTime(int)" << std::endl;
        this->hours +=  this->minutes / 60;
        this->minutes %= 60;
    }
    MyTime t2 = 70;

这里直接调用构造函数

Assignment operator overloading

  • Convert another type to the current
    MyTime & operator=(int m)
    {
        std::cout << "operator=(int)" << std::endl;
        this->hours = 0;
        this->minutes = m;
        this->hours =  this->minutes / 60;
        this->minutes %= 60;
        return *this;
    }
    MyTime t3;
    t3 = 80;

这里是进行赋值操作

Be careful

  • What is the difference in creating object t2 and t3

初始化和赋值的区别

Example4

time.hpp

#pragma once
#include <iostream>

class MyTime
{
    int hours;
    int minutes;
  public:
    MyTime(): hours(0), minutes(0)
    {
        std::cout << "Constructor MyTime()" << std::endl;
    }
    MyTime(int m): hours(0), minutes(m)
    {
        std::cout << "Constructor MyTime(int)" << std::endl;
        this->hours +=  this->minutes / 60;
        this->minutes %= 60;
    }
    MyTime(int h, int m): hours(h), minutes(m)
    {
        std::cout << "Constructor MyTime(int,int)" << std::endl;
    }
    
    //implicit conversion
    operator int() const
    {
        std::cout << "operator int()" << std::endl;
        return this->hours * 60 + this->minutes;
    }
    //explicit conversion
    explicit operator float() const
    {
        std::cout << "explicit operator float()" << std::endl;
        return float(this->hours * 60 + this->minutes);
    }

    MyTime & operator=(int m)
    {
        std::cout << "operator=(int)" << std::endl;
        this->hours = 0;
        this->minutes = m;
        this->hours =  this->minutes / 60;
        this->minutes %= 60;
        return *this;
    }

    friend std::ostream & operator<<(std::ostream & os, const MyTime & t)
    {
        std::string str = std::to_string(t.hours) + " hours and " 
                        + std::to_string(t.minutes) + " minutes.";
        os << str;
        return os;
    }
};

main.cpp

#include <iostream>
#include "time.hpp"

using namespace std;

int main()
{
    MyTime t1(1, 20);
    int minutes = t1; //implicit conversion
    float f = float(t1); //explicit conversion. 
    std::cout << "minutes = " << minutes << std::endl;
    std::cout << "minutes = " << f << std::endl;

    MyTime t2 = 70;
    std::cout << "t2 is " << t2 << std::endl;

    MyTime t3;
    t3 = 80;
    std::cout << "t3 is " << t3 << std::endl;

    return 0;

}


Constructor MyTime(int,int)
operator int()
explicit operator float()
minutes = 80
minutes = 80
Constructor MyTime(int)
t2 is 1 hours and 10 minutes.
Constructor MyTime()
operator=(int)
t3 is 1 hours and 20 minutes.

5- Increment and Decrement Operators

自增和自减运算符

Increment

  • Two operators: prefix increment & postfix increment
    // prefix increment
    MyTime& operator++()
    {
        std::cout << "operator prefix increment" << std::endl;
        this->minutes++;
        this->hours += this->minutes / 60;
        this->minutes = this->minutes % 60;
        return *this; 
    }
 
    // postfix increment
    MyTime operator++(int)
    {
        std::cout << "operator postfix increment" << std::endl;
        MyTime old = *this; // keep the old value
        operator++();  // prefix increment
        return old; 
    }

Example5

time.hpp

#pragma once
#include <iostream>

class MyTime
{
    int hours;
    int minutes;
  public:
    MyTime(): hours(0), minutes(0)
    {
        std::cout << "Constructor MyTime()" << std::endl;
    }
    MyTime(int m): hours(0), minutes(m)
    {
        std::cout << "Constructor MyTime(int)" << std::endl;
        this->hours +=  this->minutes / 60;
        this->minutes %= 60;
    }
    MyTime(int h, int m): hours(h), minutes(m)
    {
        std::cout << "Constructor MyTime(int,int)" << std::endl;
    }

    // prefix increment
    MyTime& operator++()
    {
        this->minutes++;
        this->hours += this->minutes / 60;
        this->minutes = this->minutes % 60;
        return *this; 
    }
 
    // postfix increment
    MyTime operator++(int)
    {
        MyTime old = *this; // keep the old value
        operator++();  // prefix increment
        return old; 
    }

    friend std::ostream & operator<<(std::ostream & os, const MyTime & t)
    {
        std::string str = std::to_string(t.hours) + " hours and " 
                        + std::to_string(t.minutes) + " minutes.";
        os << str;
        return os;
    }
};

main.cpp

#include <iostream>
#include "time.hpp"

using namespace std;

int main()
{
    MyTime t1(1, 59);
    MyTime t2 = t1++;
    MyTime t3 = ++t1;

    std::cout << "t1 is " << t1 << std::endl;
    std::cout << "t2 is " << t2 << std::endl;
    std::cout << "t3 is " << t3 << std::endl;

    return 0;

}


Constructor MyTime(int,int)
operator postfix increment
operator prefix increment
operator prefix increment
t1 is 2 hours and 1 minutes.
t2 is 1 hours and 59 minutes.
t3 is 2 hours and 1 minutes.

Operators

  • Operators which can be overloaded

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值