将虚拟成员方法传递给thread()

时间:2014-08-20 18:04:39

标签: c++ inheritance

我试图将虚拟方法传递给线程类'构造函数(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

非常感谢任何帮助。

2 个答案:

答案 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:

中使用私人线程t
class 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()。