所以我的问题开始很像这个问题:
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
方法之外,还有其他解决方法吗?
答案 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);
}