一、前言
什么是回調函數?各類語言中都存在回調函數,C語言和C++一系列語言中通過回調機制實現模塊化、多態化、不同模塊的參數傳遞。
回調機制,c語言和c++的回調機制主要通過函數指針來實現。
typedef T(*PFuncCallback)(T1 param1,T2 param2);
二、c語言多態例子
//聲明回調類型函數PSayHelloCallback //@void 為返回來興 //@name 參數一,表示名字 //@context 上下文,c語言中一般為nullptr typedef void(*PSayHelloCallback)(const char * name,void * context); //定義一個函數指針實體 PSayHelloCallback phelloCallback; void SayHelloEnglish(const char* name,void * context) { printf("Hello,I'm %s.\n",name); } void SayHelloChinese(const char* name, void * context) { printf("你好,我是%s。\n", name); } void RegistCallFunc(PSayHelloCallback phello) { phelloCallback = phello;
調用
RegistCallFunc(SayHelloEnglish); //通過函數指針,把所需的函數傳入,通過一個全局指針實現,可以實現c語言的多態,根據需要調用 phelloCallback("lilei",nullptr); RegistCallFunc(SayHelloChinese); phelloCallback("李雷", nullptr);
三、C語言傳參的例子
///傳值例子 //庫提供方的函數指針 typedef void(pOutputCallback)(int ra); //庫提供方提供的函數 void PrintINT(pOutputCallback pOut) { pOut(5); } void Output(int ra) { printf("數字是%d\n",ra); } 主函數中 PrintINT(Output); //通過函數指針把外部定義的函數,傳入調用方供調用方調用,所以稱回調,函數外部定義解析,這樣就可以實現接收庫提供的數據
四、c++回調函數的實現
對於c++,是面向對象的語言,回調的時候,是哪個實體?所以需要注冊回調的時候傳入對象實例;c++具有封裝性,本類內的回調是沒有意義的,所以需要把回調函數設置成靜態成員函數或者友元函數。
typedef void(*PFucnCallback)(string name,void* context); class CPerson { public: CPerson() {} ~CPerson() {} CPerson(int age,string name); void PrintInfo(); static void OnSayHello(string name, void* context) { cout << "hello world!I'm"<<name<<"." << endl; } void RegistCallback(PFucnCallback pf,void* context); private: int m_age; string m_name; }; CPerson::CPerson(int age, string name){ m_age = age; m_name = name; } void CPerson::PrintInfo() { cout << "我叫" << m_name << ",我今年" << m_age << "歲。" << endl; } //由於靜態函數不能訪問類成員,回調傳入的對象要在此解析,解析后調用回調函數 void CPerson::RegistCallback(PFucnCallback pf, void* context) { CPerson* person = (CPerson*)context; if (person) pf(person->m_name, nullptr); } int main() { CPerson *person = new CPerson(10,"李明"); CPerson *person2 = new CPerson(11, "小文"); //需要顯示誰的成員,就傳入誰,類似的友元函數也能實現賜個回調 //友元函數實現只能自身的對象調用,比靜態函數實現具有局限性 person->RegistCallback(CPerson::OnSayHello, person2); std::getchar(); return 0; }
五、c++11回調函數的實現
c++11引入了bind函數,它在functional頭文件中,與之匹配的承接者可以用funciton()來構造,實際中使用auto就可以了。
class CPerson { public: CPerson() {} ~CPerson() {} CPerson(int age,string name); void PrintInfo(); private: int m_age; string m_name; }; CPerson::CPerson(int age, string name){ m_age = age; m_name = name; } void CPerson::PrintInfo() { cout << "我叫" << m_name << ",我今年" << m_age << "歲。" << endl; } int main() { CPerson *person = new CPerson(10,"李明"); CPerson *person2 = new CPerson(11, "小文"); //callback 的實際類型是function(void(void)),auto是推導 //function 實際是一個函數指針,可以承接函數,lambd表達式,其他可調用對象 //std::placeholders標識占位符號 auto callback = bind(&CPerson::PrintInfo,person); callback(); std::getchar(); return 0; }