c++中函數(shù)調(diào)用運(yùn)算符重載的實(shí)現(xiàn)
在 C++ 中,函數(shù)調(diào)用運(yùn)算符 () 的重載是一種特殊的運(yùn)算符重載方式,允許自定義類的對象像函數(shù)一樣被調(diào)用(這類對象也被稱為 “函數(shù)對象” 或 “仿函數(shù)”)。函數(shù)調(diào)用運(yùn)算符重載是實(shí)現(xiàn) STL 算法(如sort、for_each)自定義邏輯的核心手段,也是現(xiàn)代 C++ 中 lambda 表達(dá)式的底層實(shí)現(xiàn)基礎(chǔ)。
一、核心規(guī)則
1、重載方式:只能作為類的成員函數(shù)重載(全局函數(shù)無法重載())。
2、返回值:無固定要求(可返回任意類型,如int、bool、自定義類型,也可void)。
3、參數(shù)列表:支持任意數(shù)量、任意類型的參數(shù)(可重載多個版本,區(qū)分參數(shù)類型 / 個數(shù))。
4、const 修飾:若函數(shù)對象無需修改自身狀態(tài),建議加const(保證常量對象可調(diào)用)。
5、語義:調(diào)用對象(參數(shù))等價于調(diào)用對象.operator()(參數(shù))。
二、基礎(chǔ)示例:簡單仿函數(shù)
先實(shí)現(xiàn)一個最基礎(chǔ)的函數(shù)調(diào)用運(yùn)算符重載,讓對象能像函數(shù)一樣執(zhí)行邏輯:
#include <iostream>
using namespace std;
// 定義一個可調(diào)用的類(仿函數(shù))
class Add {
public:
// 重載函數(shù)調(diào)用運(yùn)算符:接收兩個int,返回和
int operator()(int a, int b) const {
return a + b;
}
};
int main() {
// 創(chuàng)建函數(shù)對象
Add add_obj;
// 像調(diào)用函數(shù)一樣調(diào)用對象(等價于 add_obj.operator()(3,5))
int result = add_obj(3, 5);
cout << "3 + 5 = " << result << endl; // 輸出:3 + 5 = 8
// 也可直接創(chuàng)建臨時對象并調(diào)用
cout << "10 + 20 = " << Add()(10, 20) << endl; // 輸出:10 + 20 = 30
return 0;
}
三、進(jìn)階示例:帶狀態(tài)的仿函數(shù)
函數(shù)對象的核心優(yōu)勢是可保存狀態(tài)(成員變量),這是普通函數(shù)無法做到的。例如實(shí)現(xiàn)一個 “累加器”:
#include <iostream>
using namespace std;
class Accumulator {
private:
int total = 0; // 保存累加狀態(tài)
public:
// 重載1:接收int,累加并返回當(dāng)前總和
int operator()(int num) {
total += num;
return total;
}
// 重載2:無參版本,返回當(dāng)前總和
int operator()() const {
return total;
}
// 重置狀態(tài)
void reset() {
total = 0;
}
};
int main() {
Accumulator acc;
// 多次調(diào)用,累計(jì)狀態(tài)
acc(10); // total = 10
acc(20); // total = 30
acc(30); // total = 60
cout << "累計(jì)總和:" << acc() << endl; // 輸出:60
acc.reset();
acc(5);
cout << "重置后累計(jì):" << acc() << endl; // 輸出:5
return 0;
}
四、實(shí)戰(zhàn)場景:配合 STL 算法使用
函數(shù)調(diào)用運(yùn)算符重載最常用的場景是為 STL 算法提供自定義邏輯(如排序、遍歷、篩選)。
示例 1:自定義排序規(guī)則
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 按年齡降序排序的仿函數(shù)
class CompareAgeDesc {
public:
// 假設(shè)元素是pair<姓名, 年齡>
bool operator()(const pair<string, int>& a, const pair<string, int>& b) const {
return a.second > b.second; // 降序:a的年齡 > b的年齡則a排在前面
}
};
int main() {
vector<pair<string, int>> students = {
{"張三", 20}, {"李四", 25}, {"王五", 18}
};
// 使用仿函數(shù)作為排序規(guī)則
sort(students.begin(), students.end(), CompareAgeDesc());
// 輸出排序結(jié)果
for (const auto& s : students) {
cout << s.first << ":" << s.second << "歲" << endl;
}
return 0;
}
示例 2:遍歷容器并累加
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 累加容器中元素的仿函數(shù)
class SumInt {
private:
int sum = 0;
public:
// 重載():接收int,累加
void operator()(int num) {
sum += num;
}
// 獲取累加結(jié)果
int getSum() const {
return sum;
}
};
int main() {
vector<int> nums = {1, 2, 3, 4, 5};
// 用for_each遍歷,傳入仿函數(shù)
SumInt sum_obj = for_each(nums.begin(), nums.end(), SumInt());
cout << "數(shù)組總和:" << sum_obj.getSum() << endl; // 輸出:15
return 0;
}
五、關(guān)鍵注意事項(xiàng)
1、與普通函數(shù)的區(qū)別:
函數(shù)對象可保存狀態(tài)(成員變量),普通函數(shù)只能通過全局 / 靜態(tài)變量實(shí)現(xiàn)(不推薦);
函數(shù)對象支持重載(多個operator()版本,區(qū)分參數(shù)),普通函數(shù)重載需手動寫多個函數(shù)名。
2、const 正確性:
若仿函數(shù)無需修改自身狀態(tài),務(wù)必給operator()加const(如排序規(guī)則的仿函數(shù));
加const后,常量對象也能調(diào)用該運(yùn)算符。
3、與 lambda 表達(dá)式的關(guān)系:
C++11 后的 lambda 表達(dá)式本質(zhì)是編譯器自動生成的 “匿名仿函數(shù)”;
上述排序示例用 lambda 簡化:
sort(students.begin(), students.end(),
[](const pair<string, int>& a, const pair<string, int>& b) {
return a.second > b.second;
});
4、重載多個版本:
可根據(jù)參數(shù)類型 / 個數(shù)重載多個operator(),滿足不同調(diào)用場景:
class Calc {
public:
int operator()(int a, int b) const { return a + b; }
double operator()(double a, double b) const { return a * b; }
int operator()(int a) const { return a * 2; }
};
// 調(diào)用
Calc calc;
cout << calc(3,5) << endl; // 8(int加法)
cout << calc(2.5, 4.0) << endl;// 10.0(double乘法)
cout << calc(6) << endl; // 12(int翻倍)
5、不可重載為全局函數(shù):
operator() 是成員函數(shù)專屬的重載運(yùn)算符,全局函數(shù)無法重載(因?yàn)閷ο?)的語法要求左操作數(shù)是類對象)。
六、總結(jié)
函數(shù)調(diào)用運(yùn)算符重載的核心價值是:
讓類對象擁有 “函數(shù)行為”,兼具函數(shù)的靈活性和類的狀態(tài)管理能力;
是 STL 算法自定義邏輯的核心手段,也是 lambda 表達(dá)式的底層支撐;
重載時需注意const修飾(無狀態(tài)時必加),并根據(jù)場景設(shè)計(jì)參數(shù)和返回值。
相比普通函數(shù),函數(shù)對象(仿函數(shù))在需要 “帶狀態(tài)的函數(shù)邏輯” 或 “重載不同參數(shù)的函數(shù)行為” 時,優(yōu)勢尤為明顯。
到此這篇關(guān)于c++中函數(shù)調(diào)用運(yùn)算符重載的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)c++ 函數(shù)調(diào)用運(yùn)算符重載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言實(shí)現(xiàn)順序表的基本操作指南(注釋很詳細(xì))
線性表是最簡單的數(shù)據(jù)結(jié)構(gòu),而順序表又是最簡單的線性表,其基本思想是用一段地址連續(xù)的儲存單元依次存儲線性表的數(shù)據(jù)元素,下面這篇文章主要給大家介紹了關(guān)于C語言實(shí)現(xiàn)順序表的基本操作,需要的朋友可以參考下2021-10-10
C語言實(shí)現(xiàn)查詢自動售貨機(jī)中的商品價格【實(shí)例分享】
本文主要介紹了C語言實(shí)現(xiàn)查詢自動售貨機(jī)中的商品價格的相關(guān)資料。具有很好的參考價值。下面跟著小編一起來看下吧2017-04-04
C++實(shí)現(xiàn)LeetCode(152.求最大子數(shù)組乘積)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(152.求最大子數(shù)組乘積),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
C++虛繼承的實(shí)現(xiàn)原理由內(nèi)存布局開始講起
為了解決多繼承時的命名沖突和冗余數(shù)據(jù)問題,C++提出了虛繼承,使得在派生類中只保留一份間接基類的成員,下面我們從內(nèi)存布局看看虛繼承的實(shí)現(xiàn)原理2022-06-06
C++中Copy-Swap實(shí)現(xiàn)拷貝交換
本文主要介紹了C++中Copy-Swap實(shí)現(xiàn)拷貝交換,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
C++ 右值引用(rvalue references)與移動語義(move semanti
文章主要介紹了C++右值引用和移動語義的設(shè)計(jì)動機(jī)、基本概念、實(shí)現(xiàn)方式以及在實(shí)際編程中的應(yīng)用,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2025-12-12

