【问题标题】:Pass method as callback from one class to other class将方法作为回调从一个类传递到另一个类
【发布时间】:2013-11-17 23:09:53
【问题描述】:

我有 2 个类,我想通过回调将一个方法从一个传递到另一个!

看到我也希望使用 void (*callBack)(); 来保存这个方法的地址

我习惯用C做这个,但我不知道如何用c++做这个;

#include <iostream>

using namespace std;

class A
{
    private:
        void (*callBack)(); //to hold the address of the method

    public:
        A();
        void setCallBack(void(*cB)());
        void useCallBack();
};


A::A()
{

}

void A::setCallBack(void(*cB)())
{
    callBack = cB;
}

void A::useCallBack()
{
    callBack();
}


class B
{
    private:
        A * Aguy;

    public:
        B();
        void someMethod();
        void otherMethod();
};

B::B()
{
    Aguy = new A();
}

void B::otherMethod()
{
    Aguy->setCallBack(someMethod);
    Aguy->useCallBack()
}

void B::someMethod()
{
    cout << "Hello. I'm from class b" << endl;
}

int main()
{
    B Bguy;
    Bguy.otherMethod();

    return 0;
}

【问题讨论】:

  • 在 C++ 中看到回调函数并不常见。您通常使用虚拟方法定义接口。然后传递一个实现接口的对象。然后您的对象可以使用接口对象。如果你真的想要回调函数,那么std::function&lt;&gt; 提供了一个围绕泛型函数的抽象方法,包括函数/方法/仿函数。

标签: c++ class methods callback


【解决方案1】:

问题是:

    void (*callBack)();

这不是指向方法的指针。这是一个指向函数的指针。
要获得指向方法的指针,您需要指定该方法所在的类。

    void (B::*callBack)();

那么当你调用它时,你需要通过一个对象来调用它。

 void A::useCallBack(B* b)
 {
      (b->*callBack)();
 }

但这可能不是你想要的。
你真正想要的是一个封装所有这些的包装器。

我会看看 std::function。这将允许您将一个方法调用和一个对象包装到一个可以调用的对象中。

std::function<void()>   callback;

只需将所有出现的void(*cB)() 替换为std::function&lt;void()&gt;,然后您就可以将对象的实例绑定到调用点的方法。

Aguy->setCallBack(std::bind(&B::someMethod, this));

这还允许您将任何普通函数或仿函数作为回调传递。

void print()
{    std:cout << "It worked\n";
}
...
Aguy->setCallBack(&print);

struct Printer
{
     void operator()() const
     {
         std::cout << "It worked with  obejct\n";
     }
}
...
Aguy->setCallBack(Printer());

【讨论】:

    【解决方案2】:

    如果您需要传递成员函数指针,请参阅修改后的代码。它使用现代 c++ 结构。

    #include <iostream>
    #include <functional>
    using namespace std;
    
    
    class A
    {
    private:
        typedef std::function<void()> some_void_function_type;
        some_void_function_type f_;
    public:
        A();
        void setCallBack(some_void_function_type f);
        void useCallBack();
    };
    
    
    A::A()
    {
    
    }
    
    void A::setCallBack(some_void_function_type f)
    {
        f_ = f;
    }
    
    void A::useCallBack()
    {
        f_();
    }
    
    
    class B
    {
    private:
        A * Aguy;
    
    public:
        B();
        void someMethod();
        void otherMethod();
    };
    
    B::B()
    {
        Aguy = new A();
    }
    
    void B::otherMethod()
    {
        Aguy->setCallBack(std::bind(&B::someMethod, this));
        Aguy->useCallBack();
    }
    
    void B::someMethod()
    {
        cout << "Hello. I'm from class b" << endl;
    }
    
    int main()
    {
        B Bguy;
        Bguy.otherMethod();
    
        return 0;
    }
    

    【讨论】:

    • 首选void() 而不是void(void)。您没有将函数定义为void print(void),它们更自然地表示为void print(),因此您的函数定义应该匹配。
    • 我试过这个解决方案,效果很好,谢谢
    【解决方案3】:

    详情请见c++ - <unresolved overloaded function type>

    引用答案:

    在 C++ 中,成员函数有一个隐式参数,它指向 对象(成员函数内的 this 指针)。正常 C 函数可以被认为具有不同的调用约定 从成员函数,所以他们的指针的类型 (指向成员函数的指针与指向函数的指针)是不同的,并且 不相容。 C++ 引入了一种新类型的指针,称为 指向成员的指针,只能通过提供对象来调用。

    把静态放在someMethod上:

    class B
    {
        private:
            A * Aguy;
    
        public:
            B();
            static void someMethod();
            void otherMethod();
    };
    
    void B::otherMethod() {
        Aguy->setCallBack(B::someMethod);
        Aguy->useCallBack(); // adding missing semicolon
    }
    

    【讨论】:

    • 好吧,你解决了我的问题,谢谢。但现在我有另一个!看到我正在尝试在 someMethod 中使用 C 对象! C类{私人:公共:C();无效 Cmethod(); }; void C::Cmethod() { cout Cmethod(); cout
    • @user2638146 将其作为不同的问题发布。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多