我试图将虚拟方法传递给线程类'构造函数(C ++线程)。
经过全面搜索,我只能通过非虚拟成员方法。
我的基类 A 有一个 start 方法,如下所示:
void A::start() {
thread(&A::runnable,A()); // <--- What do I change here?
}
runnable 函数是虚拟的,也可以在派生类 B 中实现。 我在派生类 B 中覆盖runnable。
然后我在 B 上调用 start 。
显然,并且不合需要的是, start 函数使用 A (而不是 B )中实现的 runnable ,因为它在 A :: start 中明确定义。 有没有办法让 runnable 函数动态绑定?
我想过使用模板和其他一些创意解决方案。 (如果没有真正的解决方案,我最终会在B中实现 start )
非常感谢任何帮助。
答案 0 :(得分:3)
显然,并且不合需要地,start函数使用在A(而不是B)中实现的runnable,因为它在A :: start中明确定义。
这对你来说很明显,但这是不正确的。当你创建一个线程时,你传递一个未命名的类A
的临时实例,它显然有A
类型,因此总是会调用A::runnable
,但你应该通过this
:< / p>
void A::start() {
thread(&A::runnable,this); // <--- What do I change here?
}
然后调用适当的虚函数。 有关详细原因,请参阅Boost::Bind and virtual function overloads: why do they work?。
答案 1 :(得分:2)
有几件事需要解决。
首先在A::start()
中创建一个匿名本地线程对象。不幸的是,只要你离开A :: start(),这个对象就会被破坏。这将触发中止。
创建线程对象时,在对象被破坏之前,您必须始终join()
或detach()
。
对于答案的其余部分,我将在A:
中使用私人线程tclass A {
...
protected:
thread t; // default constructed thread object, i.e. without associated thread of execution
public:
...
~A() {
if (t.joinable()) // If thread active and not detached, be sure that it's joined before it is destructed !!
t.join();
}
....
};
接下来,在创建线程时,使用A()
作为参数。这意味着您将创建一个新的匿名A对象并将其作为参数传递。我想这不是你打算做的,所以你改用this
。
然后,正如Slava所说,当&amp; A :: runnable与此结合使用时,它就是被调用的虚函数。所以start()应该是这样的:
void start() {
t = move (thread (&A::runnable, this )) ; // Here I create an anonymous thread and move it to t.
}
如果你运行这段代码,你会注意到为A类对象调用A :: runnable(),为B类对象调用B :: runnable()。