c++的回調函數


一、前言

什么是回調函數?各類語言中都存在回調函數,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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM