我正在编写一个基类来管理线程。这个想法是允许在子类中重写线程函数,而基类管理线程生命周期。我遇到了一个我不理解的奇怪行为-似乎是从线程进行调用时,虚函数机制无法正常工作。为了说明我的问题,我将代码简化为以下内容:
#include <iostream>
#include <thread>
using namespace std;
struct B
{
thread t;
void thread_func_non_virt()
{
thread_func();
}
virtual void thread_func()
{
cout << "B::thread_func\n";
}
B(): t(thread(&B::thread_func_non_virt, this)) { }
void join() { t.join(); }
};
struct C : B
{
virtual void thread_func() override
{
cout << "C::thread_func\n";
}
};
int main()
{
C c; // output is "B::thread_func" but "C::thread_func" is expected
c.join();
c.thread_func_non_virt(); // output "C::thread_func" as expected
}
我尝试使用Visual Studio 2017和g ++ 5.4(Ubuntu 16),发现行为是一致的。有人可以指出我错了吗?
==更新==
基于Igor的回答,我将线程创建从构造函数中移出到一个单独的方法中,并在构造函数之后调用该方法,并获得了所需的行为。
答案 0 :(得分:4)
您的程序显示未定义的行为。 *this
和thread_func
(隐式定义)的构造函数之间在C
上存在竞争。
答案 1 :(得分:0)
#include <iostream>
#include <thread>
using namespace std;
struct B
{
thread t;
void thread_func_non_virt()
{
thread_func();
}
virtual void thread_func()
{
cout << "B::thread_func\n";
}
B(B*ptr): t(thread(&B::thread_func_non_virt, ptr))
{
}
void join() { t.join(); }
};
struct C:public B
{
C():B(this){}
virtual void thread_func() override
{
cout << "C::thread_func\n";
}
};
int main()
{
C c; // "C::thread_func" is expected as expected
c.join();
c.thread_func_non_virt(); // output "C::thread_func" as expected
}