1- Operators in OpenCV
Function overloading
If the functions have the same function name, but the input parameters are different, you can define functions for different situations without having to repeatedly define new function names.
- 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; }
Two operators are overloaded: *
and <<
CMakeList.cpp
cmake_minimum_required(VERSION 3.1) set (CMAKE_CXX_STANDARD 11) project(mateexample) 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 + ()
andoperator + =()
A + B operation: this + t
A + = B operation: this + = t
Example1
time.hpp
#pragma once #include <iostream> classMyTime {<!-- --> 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 #includeclassMyTime { 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 are 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
friend function
- If we want that operator + can support (
int
+MyTime
)
MyTime t1(2, 40); 20 + t1;
- Let a friend function to help
- Friend functions
(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 & amp; 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 & amp; t); }; MyTime operator + (int m, const MyTime & t) {<!-- --> return t + m; }
- Operator
<<
can also be overloaded - but in (
cout << t1;
) , the first operand isstd::ostream
, notMyTime
- To modify the definition of
std::ostream
? NO! - Use a friend function
friend std::ostream & amp; operator<<(std::ostream & amp; os, const MyTime & amp; t) {<!-- --> std::string str = std::to_string(t.hours) + " hours and " + std::to_string(t.minutes) + "minutes."; os << str; return os; } friend std::istream & amp; operator>>(std::istream & amp; is, MyTime & amp; t) {<!-- --> is >> t.hours >> t.minutes; t.hours + = t.minutes / 60; t.minutes %= 60; return is; }
- return The return value must be of
std::i/ostream & amp;
type, otherwise chain output cannot be performed, such as modifyingfriend int operator << (...) {...return o }
std::cout << t1 << std::endl; => 0 << std::endl;
Unable to chain calls
Example3
time.hpp
#pragma once #includeclassMyTime { 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 & amp; 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 & amp; operator<<(std::ostream & amp; os, const MyTime & amp; t) {<!-- --> std::string str = std::to_string(t.hours) + " hours and " + std::to_string(t.minutes) + "minutes."; os << str; return os; } friend std::istream & amp; operator>>(std::istream & amp; is, MyTime & amp; 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
Want to convert MyTime
into an integer, operator int()
Added explicit
: conversion must be explicit, not implicit conversion
- if:
MyTime t1(1, 20); int minutes = t1; //implicit conversion float f = t1; // explicit conversion
This will not report an error, because operator int()
is automatically called to convert it to an integer, and then it is forced to convert it to the float
type.
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;
Call the constructor directly here
Assignment operator overloading
- Convert another type to the current
MyTime & amp; 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;
Here is the assignment operation
Be careful
- What is the difference in creating object
t2
andt3
The difference between initialization and assignment
Example4
time.hpp
#pragma once #include <iostream> classMyTime {<!-- --> 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 & amp; operator<<(std::ostream & amp; os, const MyTime & amp; 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 hour and 20 minutes.
5- Increment and Decrement Operators
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> classMyTime {<!-- --> 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 & amp; operator<<(std::ostream & amp; os, const MyTime & amp; 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 hour and 59 minutes. t3 is 2 hours and 1 minutes.
Operators
- Operators which can be overloaded