Начать поток с функции-члена (с наследованием) - PullRequest
0 голосов
/ 28 декабря 2018

Итак, моя проблема начинается примерно так:
Запуск потока с функцией-членом

У меня есть класс 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 голосов
/ 28 декабря 2018

Вы можете просто сделать set virtual:

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

struct Bar : Foo
{
    void set(int x) override;
};
0 голосов
/ 28 декабря 2018

Хотя ответ уже принят, вот способ сделать то же самое, используя 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;
}

Также, без использования лямбды, вы могли бы сделать это также:

void plan(int x){
    t = std::thread (&Foo::set, this, x);
}
0 голосов
/ 28 декабря 2018

Просто пометьте set как virtual и используйте лямбда-версию, соблюдая осторожность, чтобы захватить все по значению, поскольку вызов 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 вызывается в производном классе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...