用成员函数启动线程(带有继承)

时间:2018-12-27 23:32:15

标签: c++ multithreading inheritance

所以我的问题开始很像这个问题:
Start thread with member function

我有一些Foo类,看起来像这样:

struct Foo
{
    int y;
    thread t;

    void set(int x){
       y = x;
    }

    void plan(int x){
        thread = std::thread ([&]{
        set(x);
    });

    void get(){
        if (t.joinable())
            t.join();
    }
};

其他答案也表明:

    void plan(int x){
        thread = std::thread(&Foo::set, this, x);
    };

现在,我想使用Foo作为带有重载set()函数的各种子类的基类,例如:

struct Bar: public Foo
{
    void set(int x){
       y = x*2;
    }
}

我的问题是,如果这样做,Bar::plan()会导致Foo::set()在新线程中运行,而不是预期的Bar::set

除了必须在plan()的每个子类中再次编写Foo方法之外,还有其他解决方法吗?

3 个答案:

答案 0 :(得分:3)

您可以简单地制作set virtual

struct Foo
{
    // ...
    virtual void set(int x);
};

struct Bar : Foo
{
    void set(int x) override;
};

答案 1 :(得分:2)

只需将set标记为virtual并使用lambda版本,请注意按值捕获所有内容,因为plan调用可能会(并且很可能会)在线程实际开始之前返回运行。

struct Foo
{
    int y;
    thread t;

    virtual void set(int x){
       y = x;
    }

    void plan(int x){
        t = std::thread ([this, x]{
            this->set(x);
        });
    }

    void get(){
        if (t.joinable())
            t.join();
    }
};

即使在派生类中调用set,也会调用正确的plan版本。

答案 2 :(得分:1)

尽管答案已经被接受,但这是一种使用std :: bind进行相同操作的方法。

#include <iostream>
#include <thread>
#include <functional>

using namespace std;

struct Foo
{
    int y;
    thread t;

    virtual void set(int x){
       y = x;
    }

    void plan(int x){
        t = std::thread (std::bind(&Foo::set, this, x));
    }

    void get(){
        if (t.joinable())
            t.join();
    }
};

struct Bar: public Foo
{
    void set(int x){
        cout << "Called" << endl;
       y = x*2;
    }
};

int main() {
    Bar b;
    b.plan(2);
    b.get();

    return 0;
}

此外,如果不使用lambda,您也可以这样做:

void plan(int x){
    t = std::thread (&Foo::set, this, x);
}