Contents
Operator overloading redefines existing operators to give them another function, allowing them to work with different data types.
I. Addition Operator Overloading
Purpose: Implement addition for two custom data types.
1.1 Overload the + operator with a member function
例:
class Person{
Person operator+(Person &p){
Person temp;
temp.m_A = this->m_A + p.m_A;
temp.m_B = this->m_B + p.m_B;
return temp;
}
int m_A;
int m_B;
};
How to call it:
- Underlying call:
Person p3 = p1.operator+(p2); - Simplified call:
Person p3 = p1 + p2;
1.2 Overload the + operator with a global function
Person operator+(Person &p1, Person &p2){
Person temp;
temp.m_A = p1.m_A + p2.m_A;
temp.m_B = p1.m_B + p2.m_B;
return temp;
}
Person operator+(Person &p1, int num){
Person temp;
temp.m_A = p1.m_A + num;
temp.m_B = p1.m_B + num;
return temp;
}
How to call it:
- Underlying call:
Person p3 = operator+(p1, p2); - Simplified call:
Person p3 = p1 + p2;
Operator overloading can itself involve function overloading:
Person p3 = p1 + p2;
Person p4 = p1 + 100;
1.3 Notes:
- Operators in expressions involving built-in data types cannot be changed.
- Do not overuse operator overloading.
II. Left-Shift Operator Overloading
Overload the << left-shift operator with a global function
ostream& operator<<(ostream &cout,Person &p){
cout << "p.m_A = " << p.m_A << endl;
cout << "p.m_B = " << p.m_B << endl;
return cout;
}
- Select cout, right-click, and choose Go to Declaration. You can then see that cout belongs to the ostream class.
- Returning cout enables method chaining, allowing additional << operators to be appended indefinitely.
- A member-function overload is not used because it could only implement p.operator<<(cout), which is p<<cout and does not match the expected behavior.
How to call it:
cout << p << endl;
III. Increment Operator Overloading
class MyInteger{
public:
MyInteger(){
m_Num = 0;
}
//重载前置++运算符
MyInteger& operator++(){
++m_Num;
return *this;
}
//重载后置++运算符 此处的int代表占位参数,可以用于区分前置和后置递增
MyInteger operator++(int){
MyInteger temp = *this;
m_Num++;
return temp;
}
private:
int m_Num;
};
Prefix ++:
- The return value is a reference so that ++(++a) can be implemented, ensuring that each increment operates on the same data.
Postfix ++:
- Because postfix ++ must return the current value before incrementing it, first save the current value, increment it, and then return the saved value.
- The return value is passed by value because temp is a local object, and a local object cannot be returned by reference.
IV. Assignment Operator Overloading
The C++ compiler adds at least four functions to a class:
- A default constructor (no parameters and an empty function body)
- A default destructor (no parameters and an empty function body)
- A default copy constructor that copies property values
- An assignment operator, operator=, that copies property values
If a class has a property that points to the heap, assignment can also cause shallow-copy and deep-copy issues.
Solution: Use a deep copy to solve the problems caused by shallow copying.
#include<iostream>
using namespace std;
class Person{
public:
Person(int age){
m_Age = new int(age);
}
~Person(){
if(m_Age != NULL){
delete m_Age;
m_Age = NULL;
}
}
//重载赋值运算符
Person& operator=(Person &p){
//先判断是否有属性在堆区,如果有,先释放干净,再深拷贝
if(m_Age != NULL){
delete m_Age;
m_Age = NULL;
}
//进行深拷贝
m_Age = new int(*p.m_Age);
return *this;
}
int *m_Age;
};
void test01(){
Person p1(18);
Person p2(20);
Person p3(24);
p3 = p2 = p1;
cout << "p1.m_Age = " << *p1.m_Age << endl;
cout << "p2.m_Age = " << *p2.m_Age << endl;
cout << "p3.m_Age = " << *p3.m_Age << endl;
}
int main(){
test01();
system("pause");
return 0;
}
Notes:
- The logic of overloading = is as follows: for p2=p1, first release the property in p2 (because with a shallow copy, m_Age in p2 and p1 points to the same memory), and then allocate new memory for a deep copy.
- The return value is Person& to allow chained assignment.
V. Relational Operator Overloading
Purpose: Overloading relational operators allows two objects of custom types to be compared. (For example, == and !=)
//例:重载==运算符
bool operator==(Person &p){
if(this->m_Name == p.m_Name && this->m_Age == p.m_Age){
return true;
}
else{
return false;
}
}
VI. Function-Call Operator Overloading
- The function-call operator is ().
- Because an overloaded function-call operator is used much like a function call, it is called a function object.
- Function objects have no fixed implementation and are highly flexible.
//例:重载()实现自定义打印
class MyPrint{
public:
void operator()(string test){
cout << test << endl;
}
};
---------
//调用方法
MyPrint myprint;
myprint("hello world");
Overloading () closely resembles a function call. For example, the functionality above can also be implemented with a function.
void myPrint(string test){ cout << test << endl; } --------- myPrint("hello world")
Reference: A Meticulously Crafted Work by Heima Programmer | C++ Tutorial: Start at 0 and Advance Through 1, Making Programming Easier Link: https://www.bilibili.com/video/BV1et411b73Z
![[C++ Notes] Operator Overloading](https://img.mahaofei.com/img/20220410093451.png)
Comments