C++回調函數學習

C++回調函數學習

  • 遇到問題,要學習C++回調函數

遇到問題,要學習C++回調函數

來吧,直接看代碼吧
共有4種方法,每種方法都有標識,對用的屏蔽和打開就可以使用
原文在這里:

#include<iostream>
#include<functional>//*2.1 普通函數作為回調函數*//
//void ProgramA_FunA1() { printf("I'am ProgramA_FunA1 and be called..\n"); }
//void ProgramA_FunA2() { printf("I'am ProgramA_FunA2 and be called..\n"); }
//
//void programB_FunB1(void(*callback)()) 
//{
//	printf("I'am ProgramB_FunB1 and be called..\n");
//	callback();
//}
//
//int main(/*int argc, char **argv*/)
//{
//	ProgramA_FunA1();
//	programB_FunB1(ProgramA_FunA2);
//}*2.2 類的靜態函數作為回調函數*//
//class ProgramA
//{
//public:
//	void FunA1() { printf("I'am ProgramA_FunA1 and be called..\n"); }
//
//	static void FunA2() { printf("I'am ProgramA_FunA2 and be called..\n"); }
//};
//
//class ProgramB 
//{
//	public:
//		static void FunB1(void(callback)()) 
//		{
//			printf("I'am ProgramB_FunB1 and be called..\n");
//			callback();
//		}
//};
//
//int main()
//{
//	ProgramA Pa;
//	Pa.FunA1();
//
//	ProgramB Pb;
//	Pb.FunB1(ProgramA::FunA2);
//}//****可以看出,以上兩種方式沒有什么本質的區別。
//****但這種實現有一個很明顯的缺點:static 函數
//****不能訪問非static 成員變量或函數,會嚴重限制回調函數可以實現的功能。***2.3 類的非靜態函數作為回調函數*//
//class ProgramA
//{
//public:
//	void FunA1() { printf("I'am ProgramA_FunA1 and be called..\n"); }
//
//	void FunA2() { printf("I'am ProgramA_FunA2 and be called..\n"); }
//};
//
//class ProgramB
//{
//public:
//	void FunB1(void (ProgramA::*callback)(),void *context) 
//	{
//		printf("I'am ProgramB_FunB1 and be called..\n");
//		((ProgramA*)context->*callback)();
//	}
//};
//
//int main()
//{
//	ProgramA Pa;
//	Pa.FunA1();
//
//	ProgramB Pb;
//	Pb.FunB1(&ProgramA::FunA2,&Pa);
//}
/******這種方法可以得到預期的結果,看似完美,但是也存在明顯不足。
*******比如在programB中FunB1還使用 programA的類型,也就我預先還要知道
*******回調函數所屬的類定義,當programB想獨立封裝時就不好用了。*///*2.4 這里還有一種方法可以避免這樣的問題,可以把非static的回調函數 包裝為另一個static函數,這種方式也是一種應用比較廣的方法*//
//class ProgramA
//{
//public:
//	void FunA1() { printf("I'am ProgramA_FunA1 and be called..\n"); }
//	void FunA2() { printf("I'am ProgramA_FunA2 and be called..\n"); }
//
//	static void FunA2Wrapper(void *context)
//	{
//		printf("I'am ProgramA.FunA2Wrapper() and be called..\n");
//		((ProgramA*)context)->FunA2();  //此處調用的FunA2()是context的函數, 不是this->FunA2()
//	};
//};
//
//class ProgramB 
//{
//public:
//	void FunB1(void (ProgramA::*callback)(),void *context)
//	{
//		printf("I'am ProgramB_FunB1() and be called..\n");
//		((ProgramA *)context->*callback)();
//	}
//
//	void FunB2(void (* callback)(void*), void* context)
//	{
//		printf("I'am ProgramB.FunB2() and be called..\n");
//		callback(context);
//	}
//};
//
//int main()
//{
//	ProgramA Pa;
//	Pa.FunA1();
//
//	ProgramB Pb;
//	Pb.FunB1(&ProgramA::FunA2,&Pa);
//
//	std:: cout<< "\n" ;
//	Pb.FunB2(ProgramA::FunA2Wrapper,&Pa);
//}
//
這種方法相對于上一種,ProgramB中沒有ProgramA的任何信息了,是一種更獨立的實現方式。
FunB2()通過調用FunA2Wrapper(),實現間接的對FunA2()的調用。FunA2()可以訪問和調用對類內的任何函數和變量。
多了一個wrapper函數,也多了一些靈活性。
?

上面借助wrapper函數實現回調,雖然很靈活,但是還是不夠優秀,比如:
1)多了一個不是太有實際用處的wrapper函數。
2)wrapper中還要對傳入的指針進行強制轉換。
3)FunB2調用時,不但要指定wrapper函數的地址,還要傳入PA的地址。//*3 std::funtion和std::bind的使用*//class ProgramA
{
public:void FunA1() { printf("I'am ProgramA.FunA1 and be called..\n"); }void FunA2() { printf("I'am ProgramA.FunA2 and be called..\n"); }static void FunA3() { printf("I'am ProgramA.FunA3 and be called..\n"); }
};
class ProgramB
{typedef std::function<void()> callbackFun;
public:void FunB1(callbackFun callback) {printf("I'am ProgramB.FunB2() and be called..\n");callback();}
};void normFun() {printf("I'am normFun() and be called..\n");}int main()
{ProgramA Pa;Pa.FunA1();printf("\n");ProgramB Pb;Pb.FunB1(normFun);std::cout << "\n";Pb.FunB1(ProgramA::FunA3);printf("\n");Pb.FunB1(std::bind(&ProgramA::FunA2,&Pa));
}
//*****std::funtion支持直接傳入函數地址,或者通過std::bind指定。
//*****簡而言之,std::funtion是定義函數類型(輸入、輸出),std::bind是綁定特定的函數(具體的要調用的函數)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/78910.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/78910.shtml
英文地址,請注明出處:http://en.pswp.cn/web/78910.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PDF解析新范式:Free2AI工具實測

在數字化浪潮中,PDF文件已成為企業、政府及個人存儲與傳遞信息的核心載體。然而,PDF內容的提取與處理始終是行業痛點——無論是合同解析、研究報告整理,還是大規模知識庫構建,傳統方法常面臨效率低、成本高、準確率不足等問題。Free2AI基于智能體技術與大模型算力,為PDF內…

【JS逆向基礎】WEB自動化

前言&#xff1a;隨著互聯網的發展&#xff0c;前端技術也在不斷變化&#xff0c;數據的加載方式也不再是單純的服務端渲染了。現在你可以看到很多網站的數據可能都是通過接口的形式傳輸的&#xff0c;或者即使不是接口那也是一些 JSON 的數據&#xff0c;然后經過 JavaScript …

大型旋轉機械信號趨勢分析算法模塊

大型旋轉機械信號趨勢分析算法模塊&#xff0c;作為信號處理算法工具箱的主要功能模塊&#xff0c;可應用于各類關鍵機械部件&#xff08;軸承、齒輪、轉子等&#xff09;的信號分析、故障探測、趨勢劣化評估等&#xff0c;采用全Python語言&#xff0c;以B/S模式&#xff0c;通…

01背包專題4:小A點菜

題目背景 uim 神犇拿到了 uoi 的 ra&#xff08;鐳牌&#xff09;后&#xff0c;立刻拉著基友小 A 到了一家……餐館&#xff0c;很低端的那種。 uim 指著墻上的價目表&#xff08;太低級了沒有菜單&#xff09;&#xff0c;說&#xff1a;“隨便點”。 題目描述 不過 uim …

探索SQLMesh中的Jinja宏:提升SQL查詢的靈活性與復用性

在數據工程和數據分析領域&#xff0c;SQL是不可或缺的工具。隨著項目復雜度的增加&#xff0c;如何高效地管理和復用SQL代碼成為了一個重要課題。SQLMesh作為一款強大的工具&#xff0c;不僅支持標準的SQL語法&#xff0c;還引入了Jinja模板引擎的宏功能&#xff0c;極大地提升…

MySQL的深度分頁如何優化?

大家好&#xff0c;我是鋒哥。今天分享關于【MySQL的深度分頁如何優化?】面試題。希望對大家有幫助&#xff1b; MySQL的深度分頁如何優化? 1000道 互聯網大廠Java工程師 精選面試題-Java資源分享網 MySQL的深度分頁在處理大數據量時可能會導致性能瓶頸&#xff0c;特別是在…

SpringBoot3集成Mybatis

文章目錄 基礎使用代碼1. 創建Spring Boot 3項目并添加依賴2. 配置數據庫連接3. 創建實體類4. 創建Mapper接口5. 創建Service層6. 創建Controller層7. 主應用類 踩坑記錄1. 依賴版本不兼容2. Mapper接口掃描問題3. 數據庫連接問題4. Java版本問題 心得體會 基礎使用代碼 1. 創…

汽車加氣站操作工考試知識點總結

汽車加氣站操作工考試知識點總結 加氣站基本知識 了解加氣站類型&#xff08;CNG、LNG、LPG等&#xff09;及其特點。 熟悉加氣站的主要設備&#xff0c;如儲氣瓶組、壓縮機、加氣機、卸氣柱、安全閥等。 掌握加氣站工藝流程&#xff0c;包括卸氣、儲氣、加壓、加氣等環節。…

88、合并兩個有序數組

題目描述 給你兩個按 非遞減順序 排列的整數數組 nums1 和 nums2&#xff0c;另有兩個整數 m 和 n &#xff0c;分別表示 nums1 和 nums2 中的元素數目。 請你 合并 nums2 到 nums1 中&#xff0c;使合并后的數組同樣按 非遞減順序 排列。 注意&#xff1a;最終&#xff0c;…

在ubuntu的docker上常用的docker命令

在 Ubuntu 系統上使用 Docker 時&#xff0c;以下是最常用的前 200 個 Docker 命令&#xff0c;并按類別進行分類。這些命令涵蓋了 Docker 的基本操作、管理容器、鏡像、網絡、卷等方面的功能&#xff0c;適用于日常使用和高級管理任務。 1. 基本命令 這些是與 Docker 交互的基…

ICode國際青少年編程競賽—Python—4級訓練場—復雜嵌套循環

ICode國際青少年編程競賽—Python—4級訓練場—復雜嵌套循環 icode練習時遇到卡頓沒有思路時怎么辦&#xff0c;題目也很難找到不會的那道題&#xff5e;針對這個問題&#xff0c;我們開發了通過“步數”、“積木行數”來快速定位到你不會的題目&#xff5e; 題目會持續更新…

交替序列長度的最大值

1、題目描述 給出n個正整數&#xff0c;你可以隨意從中挑選一些數字組成 一段序列S&#xff0c;該序列滿足以下兩個條件&#xff1a; 1.奇偶交替排列&#xff1a;例如&#xff1a;"奇&#xff0c;偶&#xff0c;奇&#xff0c;偶&#xff0c;奇.…" 或者 "偶&a…

電機試驗平臺:功能架構與關鍵技術介紹

電機試驗平臺作為電機研發、生產和質量控制的核心設備&#xff0c;其設計與應用直接關系到電機性能測試的準確性和效率。隨著工業自動化、新能源汽車等領域的快速發展&#xff0c;對電機性能的要求日益提高&#xff0c;電機試驗平臺的設計也需不斷優化以適應多樣化需求。以下從…

ubuntu修改時區和設置24小時格式時間

ubuntu修改時區和設置24小時格式時間 一、修改時區二、設置24小時格式時間endl 一、修改時區 使用timedatectl命令更改當前時區為東八區[rootubuntu24-16:~]# timedatectl list-timezones | grep -i shanghai Asia/Shanghai [rootubuntu24-16:~]# timedatectl set-timezone As…

【IP101】圖像分割技術全解析:從傳統算法到深度學習的進階之路

圖像分割詳解 ?? 歡迎來到圖像處理的"手術室"&#xff01;在這里&#xff0c;我們將學習如何像外科醫生一樣精準地"切割"圖像。讓我們一起探索這個神奇的圖像"手術"世界吧&#xff01;&#x1f3e5; 目錄 &#x1f4d1; 1. 圖像分割簡介2. 閾…

URL混淆與權限繞過技術

一、漏洞原理 前后端路徑解析邏輯不一致 后端框架&#xff08;Spring/Shiro&#xff09;自動處理特殊字符&#xff08;../、//&#xff09;&#xff0c;但鑒權組件&#xff08;如Filter&#xff09;未規范化原始URI。 示例&#xff1a;/system/login/../admin被Filter誤判為白…

Redis卸載重裝教程

卸載 找到redis安裝目錄 cmd打開該目錄&#xff0c;輸入 redis-server --service-uninstall運行結果如下 最后再刪除redis文件夾即可&#xff08;如果顯示該文件夾已在其他地方被打開而無法刪除&#xff0c;可以重啟一下電腦&#xff0c;就能正常刪除啦&#xff09; 安裝R…

使用OpenCV 和 Dlib 實現人臉融合技術

文章目錄 引言一、技術概述二、環境準備三、關鍵代碼解析1. 人臉關鍵點定義2. 獲取人臉掩模3. 計算仿射變換矩陣4. 檢測并提取人臉關鍵點5. 顏色校正 四、完整流程五、效果展示六、總結 引言 本文將介紹如何使用Python、OpenCV和dlib庫實現人臉融合技術&#xff0c;將一張人臉…

skywalking服務安裝與啟動

skywalking服務安裝并啟動 1、介紹2、下載apache-skywalking-apm3、解壓縮文件4、創建數據庫及用戶5、修改配置文件6、下載 MySQL JDBC 驅動7、啟動 OAP Serve,需要jkd11,需指定jkd版本,可以修改文件oapService.sh8、啟動 Web UI,需要jkd11,需指定jkd版本,可以修改文件oapServi…

計算方法實驗四 解線性方程組的間接方法

【實驗性質】 綜合性實驗。 【實驗目的】 掌握迭代法求解線性方程組。 【實驗內容】 應用雅可比迭代法和Gauss-Sediel迭代法求解下方程組&#xff1a; 【理論基礎】 線性方程組的數值解法分直接算法和迭代算法。迭代法將方程組的求解轉化為構造一個向量序列&…