Mat*_*Mat 8 c++ oop eiffel member-function-pointers callback
是否有一些库允许我在c ++中轻松方便地创建面向对象的回调?
例如,埃菲尔的语言具有"代理人"的概念,其或多或少的工作方式如下:
class Foo{
public:
Bar* bar;
Foo(){
bar = new Bar();
bar->publisher.extend(agent say(?,"Hi from Foo!", ?));
bar->invokeCallback();
}
say(string strA, string strB, int number){
print(strA + " " + strB + " " + number.out);
}
}
class Bar{
public:
ActionSequence<string, int> publisher;
Bar(){}
invokeCallback(){
publisher.call("Hi from Bar!", 3);
}
}
Run Code Online (Sandbox Code Playgroud)
输出将是:嗨来自Bar!3来自Foo!
所以 - 代理允许将成员函数封装到一个对象中,沿着一些预定义的调用参数(来自Foo的Hi)给它,指定打开的参数(?),然后将它传递给其他对象,然后再调用它.
由于C++不允许创建非静态成员函数的函数指针,似乎并不容易实现容易在C++使用的东西.我在c ++中找到了一些关于面向对象回调的谷歌的文章,但是,实际上我正在寻找一些我可以导入的库或头文件,它允许我使用一些类似优雅的语法.
有人给我一些提示吗?
谢谢!
ste*_*anv 11
在C++中使用Callbacks的最OO方法是调用接口的函数,然后传递该接口的实现.
#include <iostream>
class Interface
{
public:
virtual void callback() = 0;
};
class Impl : public Interface
{
public:
virtual void callback() { std::cout << "Hi from Impl\n"; }
};
class User
{
public:
User(Interface& newCallback) : myCallback(newCallback) { }
void DoSomething() { myCallback.callback(); }
private:
Interface& myCallback;
};
int main()
{
Impl cb;
User user(cb);
user.DoSomething();
}
Run Code Online (Sandbox Code Playgroud)
人们通常使用以下几种模式之一:
遗产.也就是说,您定义了一个包含回调的抽象类.然后你拿一个指针/引用它.这意味着任何人都可以继承并提供此回调.
class Foo {
virtual void MyCallback(...) = 0;
virtual ~Foo();
};
class Base {
std::auto_ptr<Foo> ptr;
void something(...) {
ptr->MyCallback(...);
}
Base& SetCallback(Foo* newfoo) { ptr = newfoo; return *this; }
Foo* GetCallback() { return ptr; }
};
Run Code Online (Sandbox Code Playgroud)
再次继承.也就是说,您的根类是抽象的,并且用户从它继承并定义回调,而不是具有具体的类和专用的回调对象.
class Foo {
virtual void MyCallback(...) = 0;
...
};
class RealFoo : Foo {
virtual void MyCallback(...) { ... }
};
Run Code Online (Sandbox Code Playgroud)
更多的继承 - 静态.这样,您可以使用模板来更改对象的行为.它与第二个选项类似,但在编译时而不是在运行时工作,这可能会产生各种好处和缺点,具体取决于上下文.
template<typename T> class Foo {
void MyCallback(...) {
T::MyCallback(...);
}
};
class RealFoo : Foo<RealFoo> {
void MyCallback(...) {
...
}
};
Run Code Online (Sandbox Code Playgroud)
您可以使用和使用成员函数指针或常规函数指针
class Foo {
void (*callback)(...);
void something(...) { callback(...); }
Foo& SetCallback( void(*newcallback)(...) ) { callback = newcallback; return *this; }
void (*)(...) GetCallback() { return callback; }
};
Run Code Online (Sandbox Code Playgroud)
有功能对象 - 它们重载operator().您将需要使用或编写当前在std ::/boost :: function中提供的函数包装器,但我还将在此处演示一个简单的包装器.它与第一个概念类似,但隐藏了实现并接受了大量其他解决方案.我个人通常使用它作为我选择的回调方法.
class Foo {
virtual ... Call(...) = 0;
virtual ~Foo();
};
class Base {
std::auto_ptr<Foo> callback;
template<typename T> Base& SetCallback(T t) {
struct NewFoo : Foo {
T t;
NewFoo(T newt) : t(newt) {}
... Call(...) { return t(...); }
};
callback = new NewFoo<T>(t);
return this;
}
Foo* GetCallback() { return callback; }
void dosomething() { callback->Call(...); }
};
Run Code Online (Sandbox Code Playgroud)
正确的解决方案主要取决于具体情况.如果需要公开C风格的API,那么函数指针是唯一的方法(记住用户参数的void*).如果需要在运行时改变(例如,在预编译库中公开代码),则不能在此处使用静态继承.
只是一个简单的说明:我手动掀起了那些代码,所以它不会是完美的(比如函数的访问修饰符等)并且可能有一些错误.这是一个例子.