C++ 運(yùn)算符重載的使用
運(yùn)算符重載(Operator Overloading)允許為自定義類型(如類、結(jié)構(gòu)體)賦予類似內(nèi)置類型的運(yùn)算符行為,使對象之間可以使用+、-、==、<<等運(yùn)算符進(jìn)行操作,提升代碼的可讀性和易用性。
1. 基本語法
- 通過
operator關(guān)鍵字重載運(yùn)算符。 - 可以作為
成員函數(shù)或全局函數(shù)實(shí)現(xiàn)。
示例(成員函數(shù)):
class Point {
public:
int x, y;
Point(int x, int y) : x(x), y(y) {}
Point operator+(const Point& other) const {
return Point(x + other.x, y + other.y);
}
};
2. 加號運(yùn)算符重載
成員函數(shù)方式:適用于a + b,其中a為當(dāng)前對象,b為參數(shù)
class Point {
public:
int x, y;
Point(int x, int y) : x(x), y(y) {}
// 加號運(yùn)算符重載
Point operator+(const Point& other) const {
return Point(x + other.x, y + other.y);
}
};
int main() {
Point p1(1, 2), p2(3, 4);
Point p3 = p1 + p2; // 調(diào)用operator+
std::cout << p3.x << ", " << p3.y << std::endl; // 輸出4, 6
return 0;
}
全局函數(shù)方式:適用于需要支持a + b和b + a等更靈活的場景(如左操作數(shù)不是類對象)。
class Point {
public:
int x, y;
Point(int x, int y) : x(x), y(y) {}
};
Point operator+(const Point& a, const Point& b) {
return Point(a.x + b.x, a.y + b.y);
}
注意事項(xiàng)
- 推薦參數(shù)為const引用,返回新對象。
- 不建議修改參與運(yùn)算的原對象(保持加法的“無副作用”)。
- 可重載為成員函數(shù)或全局函數(shù),具體選擇視需求而定。
總結(jié):
加號運(yùn)算符重載讓自定義類型支持直觀的“加法”操作,提升代碼可讀性和易用性。
3. 左移運(yùn)算符重載
左移運(yùn)算符重載(operator<<)常用于自定義類型的輸出,使對象可以直接用std::cout << obj的方式打印內(nèi)容。通常寫成全局函數(shù),并返回ostream&以支持鏈?zhǔn)捷敵?/code>。
#include <iostream>
class Point {
public:
int x, y;
Point(int x, int y) : x(x), y(y) {}
};
// 左移運(yùn)算符重載,必須為全局函數(shù)(或友元)
std::ostream& operator<<(std::ostream& os, const Point& p) {
os << "(" << p.x << ", " << p.y << ")";
return os;
}
int main() {
Point p(3, 4);
std::cout << p << std::endl; // 輸出:(3, 4)
return 0;
}
說明與注意事項(xiàng):
- 第一個參數(shù)為std::ostream&,第二個參數(shù)為自定義類型的const引用。
- 返回ostream&,支持鏈?zhǔn)捷敵觯ㄈ鐂td::cout << p1 << p2;)。
- 通常聲明為友元函數(shù)以訪問私有成員:
friend std::ostream& operator<<(std::ostream&, const Point&);
4. 遞增運(yùn)算符
遞增運(yùn)算符重載(operator++)允許自定義類型支持前置和后置自增(如++obj和obj++)。這兩種寫法的重載方式略有不同。
前置遞增運(yùn)算符重載:
- 語法:Type& operator++();
- 用于++obj,返回自增后的對象引用。
示例:
class Counter {
int value;
public:
Counter(int v = 0) : value(v) {}
// 前置++
Counter& operator++() {
++value;
return *this;
}
int get() const { return value; }
};
后置遞增運(yùn)算符重載:
- 語法:Type operator++(int);(int是占位參數(shù),用于區(qū)分前置和后置)
- 用于obj++,返回自增前的對象副本。
示例:
class Counter {
int value;
public:
Counter(int v = 0) : value(v) {}
// 后置++
Counter operator++(int) {
Counter temp = *this;
++value;
return temp;
}
int get() const { return value; }
};
調(diào)用:
int main() {
Counter c(5);
++c; // 前置,c變?yōu)?
c++; // 后置,c變?yōu)?
std::cout << c.get() << std::endl; // 輸出7
return 0;
}
注意事項(xiàng)
- 前置返回引用,后置返回副本。
- 推薦前置效率更高,后置因需保存臨時副本略慢。
- 可根據(jù)需要只重載一種或兩種。
5. 賦值運(yùn)算符
賦值運(yùn)算符重載(operator=)允許自定義類型支持對象間的賦值操作(如a = b;)。正確實(shí)現(xiàn)賦值運(yùn)算符對于資源管理(如動態(tài)內(nèi)存)尤為重要。
基本語法:
class Demo {
public:
Demo& operator=(const Demo& other) {
if (this != &other) { // 防止自賦值
// 釋放舊資源(如有)
// 復(fù)制other的數(shù)據(jù)到當(dāng)前對象
}
return *this; // 支持鏈?zhǔn)劫x值
}
};
典型實(shí)現(xiàn):
class MyString {
char* data;
public:
MyString(const char* str = "") {
data = new char[strlen(str) + 1];
strcpy(data, str);
}
~MyString() { delete[] data; }
MyString& operator=(const MyString& other) {
if (this != &other) {
delete[] data; // 釋放舊內(nèi)存
data = new char[strlen(other.data) + 1];
strcpy(data, other.data);
}
return *this;
}
};
注意事項(xiàng):
- 防止自賦值:if (this != &other),避免自我釋放導(dǎo)致數(shù)據(jù)丟失。
- 釋放舊資源:先釋放當(dāng)前對象持有的資源,防止內(nèi)存泄漏。
- 深拷貝:如有指針成員,需分配新內(nèi)存并復(fù)制內(nèi)容。
- 返回自身引用:return *this;,支持鏈?zhǔn)劫x值(如a = b = c;)。
6. 關(guān)系運(yùn)算符重載
關(guān)系運(yùn)算符重載允許自定義類型支持比較操作(如==、!=、<、>、<=、>=),使對象之間可以像內(nèi)置類型一樣進(jìn)行比較。
常見關(guān)系運(yùn)算符重載:
- operator==:等于
- operator!=:不等于
- operator< :小于
- operator> :大于
- operator<=:小于等于
- operator>=:大于等于
示例
class Point {
public:
int x, y;
Point(int x, int y) : x(x), y(y) {}
// 等于運(yùn)算符重載
bool operator==(const Point& other) const {
return x == other.x && y == other.y;
}
// 小于運(yùn)算符重載(按字典序)
bool operator<(const Point& other) const {
return (x < other.x) || (x == other.x && y < other.y);
}
};
int main() {
Point p1(1, 2), p2(1, 2), p3(2, 3);
std::cout << std::boolalpha;
std::cout << (p1 == p2) << std::endl; // true
std::cout << (p1 < p3) << std::endl; // true
return 0;
}
注意事項(xiàng):
- 推薦參數(shù)為const引用,成員函數(shù)加const保證不修改對象。
- 只需重載==和<,其余可用標(biāo)準(zhǔn)庫std::rel_ops自動推導(dǎo)(或手動實(shí)現(xiàn))。
- 關(guān)系運(yùn)算符重載應(yīng)符合直觀語義,避免誤用。
7. 函數(shù)調(diào)用運(yùn)算符重載
函數(shù)調(diào)用運(yùn)算符重載(operator())允許對象像函數(shù)一樣被調(diào)用,這種對象稱為“仿函數(shù)”或“函數(shù)對象”。
函數(shù)調(diào)用運(yùn)算符重載(operator())
- 通過重載operator(),可以讓對象像函數(shù)一樣使用,常用于
自定義算法、回調(diào)、STL等場景。
示例:
class Adder {
int base;
public:
Adder(int b) : base(b) {}
int operator()(int x) const {
return base + x;
}
};
int main() {
Adder add5(5);
std::cout << add5(10) << std::endl; // 輸出15
return 0;
}
- 可以有多個參數(shù),也可以重載多次實(shí)現(xiàn)不同參數(shù)列表。
- 支持捕獲狀態(tài)(如成員變量),比普通函數(shù)更靈活。
8. 其他運(yùn)算符重載
下標(biāo)運(yùn)算符重載(operator[]):使對象支持?jǐn)?shù)組下標(biāo)訪問
示例:
class Array {
int data[10];
public:
int& operator[](int idx) { return data[idx]; }
};
箭頭運(yùn)算符重載(operator->):使對象像指針一樣訪問成員。
class Ptr {
Demo* p;
public:
Demo* operator->() { return p; }
};
類型轉(zhuǎn)換運(yùn)算符重載(operator 類型):實(shí)現(xiàn)對象到其他類型的隱式或顯式轉(zhuǎn)換。
class Demo {
int value;
public:
operator int() const { return value; }
};
9. 注意事項(xiàng)
- 運(yùn)算符重載應(yīng)符合直觀語義,避免濫用。
- 某些運(yùn)算符(如[]、()、->、=)必須為成員函數(shù)。
- 運(yùn)算符重載不能改變運(yùn)算符的優(yōu)先級和結(jié)合性。
到此這篇關(guān)于C++ 運(yùn)算符重載的使用的文章就介紹到這了,更多相關(guān)C++ 運(yùn)算符重載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Win32下C++實(shí)現(xiàn)快速獲取硬盤分區(qū)信息
這篇文章主要為大家詳細(xì)介紹了Win32下C++如何實(shí)現(xiàn)快速獲取硬盤分區(qū)信息,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-03-03
C語言實(shí)現(xiàn)時區(qū)轉(zhuǎn)換函數(shù)的實(shí)例
這篇文章主要介紹了C語言實(shí)現(xiàn)時區(qū)轉(zhuǎn)換函數(shù)的實(shí)例的相關(guān)資料,這里分析需求并提供實(shí)現(xiàn)代碼,需要的朋友可以參考下2017-08-08
C++ Strassen算法代碼的實(shí)現(xiàn)
這篇文章主要介紹了C++ Strassen算法代碼的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
OpenCV鼠標(biāo)繪制矩形和截取矩形區(qū)域圖像
這篇文章主要為大家詳細(xì)介紹了OpenCV鼠標(biāo)繪制矩形和截取矩形區(qū)域圖像,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-01-01

