我已经搜索了这个,但我想我只是让自己更加困惑。
我想要做的是在一个对象中保存一个函数指针,然后在另一个线程中调用它。
我想象的是一个构造函数,它将获取一个函数指针和将传递给该函数指针的参数。该对象还将有一个run()方法,它将运行所述函数指针和一个wait_until_completed()方法,该方法将一直阻塞,直到该函数运行完毕。
如果有意义的话,函数指针应该是来自另一个对象的函数。例如
Foo::*Bar(int);
我使用pthread_cond_t工作了wait_until_completed(),但我坚持使用这个函数指针的东西,觉得我只是在圈子里跑来跑去。
有什么建议吗?
编辑:这是为了学校(我的一般理解)所以第三方图书馆不能工作:/我觉得我做了一个非常差的工作来解释这个,让我给出一些示例代码(不包括所有同步的东西)
class Foo
{
public:
Foo(void (Bar::*function) (int), int function_param)
{
// Save the function pointer into this object
this->function = &function;
// Save the paramater to be passed to the function pointer in this object
param = function_param;
}
run()
{
(*function)(param);
}
private:
// The function pointer
void (Bar::*function) (int) = NULL;
// The paramater to pass the function pointer
int param;
}
这简直就是我要做的。但是,我不确定它是语法还是我是愚蠢的,但我无法弄清楚如何实际执行此操作并将其编译。
几点思考?并感谢到目前为止的所有建议:)
答案 0 :(得分:9)
首先,您需要typedef
您的函数类型,以便更轻松地重用它并减少错误的可能性。
typedef void (Bar::*function_type)(int);
现在你可以像这样使用typedef:
Foo(function_type func, int func_param)
: function_(func)
, param_(func_param)
{
}
此外,最好使用初始化列表初始化成员变量(您可以找到有关初始化列表here的更多信息)。
但是,您仍然无法调用该函数。类成员函数,也称为绑定函数必须与实例化对象一起使用,因为它们绑定。你的run
函数必须看起来像这样(你也忘了返回类型):
void run(Bar* object){
(object->*function_(param_));
}
它使用特殊的->*
运算符通过成员函数指针调用成员函数
此外,您不能直接在类中初始化大多数变量(只有静态积分常量,如static const int i = 5;
)。
现在,您将能够实例化Foo
对象并在其上调用run函数
这里有一个完全可编译的例子:
#include <iostream>
using namespace std;
class Bar{
public:
void MyBarFunction(int i){
cout << i << endl;
}
};
class Foo
{
public:
typedef void (Bar::*function_type)(int);
Foo(Bar* object, function_type function, int function_param)
: object_(object) // save the object on which to call the function later on
, function_(function) // save the function pointer
, param_(function_param) // save the parameter passed at the function
{
}
void Run()
{
(object_->*function_)(param_);
}
private:
// The object to call the function on
Bar* object_;
// The function pointer
function_type function_;
// The paramater to pass the function pointer
int param_;
};
int main(void){
// create a Bar object
Bar bar;
// create a Foo object, passing the Bar object
// and the Bar::myBarFunction as a parameter
Foo foo(&bar, &Bar::MyBarFunction, 5);
// call Bar::MyBarFunction on the previously passed Bar object 'bar'
foo.Run();
cin.get();
return 0;
}
这可能会立即消化,但我希望这有助于您了解成员函数指针以及如何使用它们。 :)
答案 1 :(得分:4)
是的,你可以存储一个函数指针:
struct simple_callable_object
{
void (*f_)();
simple_callable_object(void (*f)()) : f_(f) { }
void operator()() { f_(); }
};
此模式在多态函数包装器function
和参数绑定器bind
中推广,可以在Boost,C ++ TR1和C ++ 0x中找到。
异步运行函数以及稍后能够阻止并等待它完成的模式被称为“未来”。 C ++ 0x线程支持库具有std::future
和std::async
,可以完成此任务。例如:
// pretend 'f' is a long-running task that you want to run asynchronously:
int f(int x) { return x * 2; }
void g()
{
std::future<int> fi = std::async(f, 21);
// do other meaningful work
int x = fi.get(); // blocks until the async task completes
}
您不必使用std::async
来获取std::future
;你可以编写一个线程池或其他一些异步完成任务并让其中一个生成并返回期货的工具。
答案 2 :(得分:3)
听起来你正试图重新发明“命令”模式。 Loki(以及许多其他人)应该给出一个合理的开始(尽管你可能不得不自己添加线程同步)。
答案 3 :(得分:2)
使用boost function对象。
编辑:这是一个简单的例子:
#include <iostream>
#include <boost/function.hpp>
struct X {
int foo(int a, int b) { return a * b; }
};
int main(void)
{
boost::function<int (X*, int, int)> func;
func = &X::foo;
X x;
std::cout << func(&x, 1, 2) <<std::endl;
return 0;
}
答案 4 :(得分:1)
关于示例代码的所有内容在技术上都是正确的,并且应该可以正常工作,除非您尝试将NULL分配给声明它的成员变量。这只能通过静态积分完成,函数指针不计算。
因此,删除该行,您的示例应该可以正常工作。
话虽如此,您应该更喜欢初始化器在构造函数体中进行赋值。它应该是这样的:
Foo(void (Bar::*fun) (int), int fparam) : function(fun), param(fparam) {}
编辑:噢,我错过了你的OP。上面你接受一个指向成员函数的指针作为你的参数但是试图把它称为普通函数。更正后的表单将使用void (*)(int)
作为您的类型,而不是void (Bar::*)(int)
。
答案 5 :(得分:0)
如果你不接受Jerry的建议,我建议使用Functors而不是搞乱使用挑剔的函数指针。
http://en.wikipedia.org/wiki/Function_object
但是,我推荐杰瑞的答案。