所以我做了一些研究,发现你可以通过使用“this”和boost :: bind等来创建一个boost :: thread对象并让它以非静态类函数开始。它真的没有对我来说很有意义,我能找到的所有例子都有boost :: thread对象在与它开始的函数相同的类中启动,因此可以使用它。然而,我在另一个类中启动线程所以我害怕使用“this”,我会说“this”来自我创建线程的类,而不是函数所在的类(我可能错了,我需要更多地了解这个“这个”家伙。以下是我遇到问题的一个例子。
ANNGUI.h
class ANNGUI { private: boost::thread *GUIThread; Main *GUIMain; public: // Creates the entire GUI and all sub-parts. int CreateGUI(); }
ANNGUI.cpp
int ANNGUI::CreateGUI() { GUIMain = new Main(); GUIThread = new boost::thread(GUIMain->MainThreadFunc); };
这不是全部来源,但我认为我的问题就在这里,我知道我必须以某种方式处理“这个”,但我不确定如何。我可以使用静态函数,但我真的不想让变量变为静态。 感谢。
此外,是否有任何非常好的资源可以使用任何升级库?他们的网站文档似乎很好,但在我的头上。
答案 0 :(得分:82)
当您创建的函数对象绑定到对象成员函数时,this
关键字与boost::bind
一起使用。成员函数不能与实例分开存在,因此当使用boost::bind
从成员函数创建functor对象时,需要指向实例的指针。这正是this
关键字实际上是什么。如果在类的成员函数中使用this
关键字,则获得的是指向该类的当前实例的指针。
如果您要从外部调用类成员函数bind
,您可能会说:
int main()
{
Foo f;
boost::thread* thr = new boost::thread(boost::bind(&Foo::some_function, &f));
}
这里,我们使用Foo :: some_function作为我们的线程函数。但我们无法使用this
,因为我们正在bind
调用main
。但如果我们从Foo的成员函数中调用this
,可以使用bind
来实现同样的目的,如下所示:
void Foo::func1()
{
boost::thread* thr = new boost::thread(boost::bind(&Foo::some_function, this));
}
如果成员函数是静态的,或者只是常规(非成员)函数,那么根本不需要实例指针。你会这样做:
boost::thread* thr = new boost::thread(some_regular_function);
答案 1 :(得分:40)
正如其他人提到的,当你想在新线程中调用对象方法时,你必须提供该对象的地址。但是你不需要调用boost::bind
,你可以像这样使用重载的boost::thread
构造函数:
GUIThread = new boost::thread(&Main::MainThreadFunc, GUIMain);
如果方法属于同一个类,则使用this
获取当前实例的地址,例如:
t = new boost::thread(&myclass::compute, this);
如果方法有参数,您可以在第二个参数后指定它们,例如:
t = new boost::thread(&myclass::compute, this, p1, p2);
答案 2 :(得分:3)
boost :: bind是你的朋友(虽然它有时会有一种粗略的方式显示它)!
使用GUIThread = new boost::thread(boost::bind(&Main::MainThreadFunc, GUIMain));
然后使您的MainThreadFunc成为常规成员。这意味着您可以像平常一样直接使用实例变量。
这样的事情:
class GUIMain {
public:
GUIMain() : m_Member(42) {}
void MainThreadFunc() {
// use all members as you would normally do
std::cout << m_Member << std::endl;
}
private:
int m_Member;
};
答案 3 :(得分:3)
在这种情况下,将非静态成员函数视为以this
作为第一个参数的自由函数是很有用的,例如在您的void MainThreadFunc(Main* this)
案例中。
boost::thread
接受一个无效的仿函数,所以你必须传递一个隐含的仿函数,其中包含对实例GUIMain
的引用,并调用GUIMain->MainThreadFunc
,如上所述,就像MainThreadFunc(GUIMain)
一样。
Boost(现在也是带有TR1的C ++)提供了帮助来创建这样的仿函数,即boost::bind
(或者boost::lambda::bind
)。表达式boost::bind(f, arg1, arg2, ...)
表示“返回一个调用f(arg1, arg2, ...)
”的无效仿函数。
也就是说,您可以使用以下表达式来创建线程:
GUIThread = new boost::thread(boost::bind(&Main::MainThreadFunc, GUIMain))
答案 4 :(得分:1)
如果您的对象是仿函数,即具有operator()
,则可以将其实例传递给boost::thread
。 operator()
不需要是静态的。例如:
#include <boost/thread.hpp>
struct th {
void operator()();
};
void th::operator()()
{
for (;;) {
// stuff
}
}
int main()
{
th t;
boost::thread my_thread( t ); // takes a copy of t !
my_thread.join(); // blocks
return 0;
}