如何在 C++ 中实现回调?

2022-01-03 00:00:00 callback c++

我想用 C++ 实现一个有回调的类.

I want to implement a class in c++ that has a callback.

所以我想我需要一个有 2 个参数的方法:

So I think I need a method that has 2 arguments:

  • 目标对象.(让我们说*myObj)
  • 指向成员函数的指针目标对象.(所以我可以做*myObj->memberFunc();)

条件是:

  • myObj 可以来自任何类.

  • myObj can be from any class.

作为回调函数的成员函数是非静态的.

the member function that is gonna be the callback function is non-static.

我一直在阅读有关此内容的信息,但似乎我需要事先了解 myObj 的类.但我不知道该怎么做.我该如何处理?这在 C++ 中可能吗?

I've been reading about this but it seems like I need to know the class of myObj before hand. But I am not sure how to do it. How can I handle this? Is this possible in C++?

这是我想到的,但肯定是不正确的.

This is something I have in mind but is surely incorrect.

class MyClassWithCallback{
public
    void *targetObj;
    void (*callback)(int number);
    void setCallback(void *myObj, void(*callbackPtr)(int number)){
        targetObj = myObj;
        callback = callbackPtr;
    };
    void callCallback(int a){
        (myObj)->ptr(a);
    };
};
class Target{
public
    int res;
    void doSomething(int a){//so something here. This is gonna be the callback function};        
};

int main(){
    Target myTarget;
    MyClassWithCallback myCaller;
    myCaller.setCallback((void *)&myTarget, &doSomething);

}

感谢您的帮助.

谢谢.

更新你们中的大多数人都说观察和委托,这正是我正在寻找的,我是一个有 Objective-C/Cocoa 头脑的人.我当前的实现是使用带有虚函数的接口.只是我认为只传递对象和成员函数指针(如 boost!)而不是定义接口会更聪明".但似乎每个人都同意接口是最简单的方法,对吗?Boost 似乎是个好主意,(假设已安装)

UPDATE Most of you said Observing and Delegation, well that's i exactly what i am looking for, I am kind of a Objective-C/Cocoa minded guy. My current implementation is using interfaces with virtual functions. Is just I thought it would be "smarter" to just pass the object and a member function pointer (like boost!) instead of defining an Interface. But It seems that everybody agrees that Interfaces are the easiest way right? Boost seems to be a good idea, (assuming is installed)

推荐答案

最好的解决方案,使用 boost::functionboost::bind,或者如果你的编译器支持 tr1/c++0x 使用 std::tr1::functionstd::tr1::bind.

The best solution, use boost::function with boost::bind, or if your compiler supports tr1/c++0x use std::tr1::function and std::tr1::bind.

所以它变得很简单:

boost::function<void()> callback;
Target myTarget;
callback=boost::bind(&Target::doSomething,&myTarget);

callback(); // calls the function

你设置的回调变成:

class MyClassWithCallback{
public:
  void setCallback(boost::function<void()> const &cb)
  {
     callback_ = cb;
  }
  void call_it() { callback_(); }
private:
  boost::function<void()> callback_;
};

否则你需要实现一些抽象类

Otherwise you need to implement some abstract class

struct callback { 
 virtual void call() = 0;
 virtual ~callback() {}
};

struct TargetCallback {
 virtual void call() { ((*self).*member)()); }
 void (Target::*member)();
 Target *self;
 TargetCallback(void (Target::*m)(),Target *p) : 
       member(m),
       self(p)
 {}
};

然后使用:

myCaller.setCallback(new TargetCallback(&Target::doSomething,&myTarget));

当您的类被修改为:

class MyClassWithCallback{
public:
  void setCallback(callback *cb)
  {
     callback_.reset(cb);
  }
  void call_it() { callback_->call(); }
private:
  std::auto_ptr<callback> callback_;
};

当然,如果你想调用的函数没有改变,你可以只实现一些接口,即通过这个调用从某个抽象类派生 Target.

And of course if the function you want to call does not change you may just implement some interface, i.e. derive Target from some abstract class with this call.

相关文章