How can I pass a class member function as a callback?

前端 未结 12 1733
忘掉有多难
忘掉有多难 2020-11-22 04:58

I\'m using an API that requires me to pass a function pointer as a callback. I\'m trying to use this API from my class but I\'m getting compilation errors.

Here is

12条回答
  •  渐次进展
    2020-11-22 05:35

    This answer is a reply to a comment above and does not work with VisualStudio 2008 but should be preferred with more recent compilers.


    Meanwhile you don't have to use a void pointer anymore and there is also no need for boost since std::bind and std::function are available. One advantage (in comparison to void pointers) is type safety since the return type and the arguments are explicitly stated using std::function:

    // std::function
    void Init(std::function f);
    

    Then you can create the function pointer with std::bind and pass it to Init:

    auto cLoggersInfraInstance = CLoggersInfra();
    auto callback = std::bind(&CLoggersInfra::RedundencyManagerCallBack, cLoggersInfraInstance);
    Init(callback);
    

    Complete example for using std::bind with member, static members and non member functions:

    #include 
    #include 
    #include 
    
    class RedundencyManager // incl. Typo ;-)
    {
    public:
        // std::function
        std::string Init(std::function f) 
        {
            return f();
        }
    };
    
    class CLoggersInfra
    {
    private:
        std::string member = "Hello from non static member callback!";
    
    public:
        static std::string RedundencyManagerCallBack()
        {
            return "Hello from static member callback!";
        }
    
        std::string NonStaticRedundencyManagerCallBack()
        {
            return member;
        }
    };
    
    std::string NonMemberCallBack()
    {
        return "Hello from non member function!";
    }
    
    int main()
    {
        auto instance = RedundencyManager();
    
        auto callback1 = std::bind(&NonMemberCallBack);
        std::cout << instance.Init(callback1) << "\n";
    
        // Similar to non member function.
        auto callback2 = std::bind(&CLoggersInfra::RedundencyManagerCallBack);
        std::cout << instance.Init(callback2) << "\n";
    
        // Class instance is passed to std::bind as second argument.
        // (heed that I call the constructor of CLoggersInfra)
        auto callback3 = std::bind(&CLoggersInfra::NonStaticRedundencyManagerCallBack,
                                   CLoggersInfra()); 
        std::cout << instance.Init(callback3) << "\n";
    }
    

    Possible output:

    Hello from non member function!
    Hello from static member callback!
    Hello from non static member callback!
    

    Furthermore using std::placeholders you can dynamically pass arguments to the callback (e.g. this enables the usage of return f("MyString"); in Init if f has a string parameter).

提交回复
热议问题