如何在C ++中实现回调? [英] How do I implement a callback in C++?

查看:115
本文介绍了如何在C ++中实现回调?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在c ++中实现一个有回调的类。



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




  • 目标对象。 (让我们说
    * myObj)

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



条件是:




  • myObj可以来自任何类别。


  • gonna是回调函数是非静态的。




我一直在阅读这篇文章,但看起来我需要知道myObj的类。但我不知道如何做到。我该如何处理?这在C ++中是可能的吗?



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

  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){//这里有东西。这将是回调函数};
};

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

}



我感谢您的帮助。



谢谢。



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

解决方案

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



变得很简单:

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

callback(); //调用函数

您的set回调函数成为:

  class MyClassWithCallback {
public:
void setCallback(boost :: function< void()> const& cb)
{
callback_ = cb;
}
void Call_it(){callback_(); }
private:
boost :: function< void()>回电话_;
};

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

  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>回电话_;
};

当然如果你想调用的函数不改变你可能只是实现一些接口,使用此调用从一些抽象类派生Target。


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

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

  • the target object. (let's say *myObj)
  • the pointer to a member function of the target object. (so i can do *myObj->memberFunc(); )

The conditions are:

  • myObj can be from any class.

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

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);

}

I appreciate any help.

Thank you.

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)

解决方案

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.

So it becomes as simple as:

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

callback(); // calls the function

And your set callback becomes:

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)
 {}
};

And then use:

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

When your class get modified into:

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

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.

这篇关于如何在C ++中实现回调?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆