[英]c++11 unexpected polymorphism beahviour when using std::thread
基于带有可变参数函数参数的C ++多态性,我尝试编写类似的(非模板,带构造函数)程序
码:
#include <thread>
#include <iostream>
#include <vector>
class Base
{
public:
Base (int count) { run(count); } // this-> does not help
virtual void run (int count) { // non-virtual does not help eighter
for (int i=0; i<count; ++i)
threads.emplace_back(std::ref(*this));
}
virtual ~Base () {
for (auto& t : threads)
t.join();
}
virtual void operator() () = 0;
protected:
std::vector< std::thread > threads;
};
class Derived : public Base
{
public:
using Base::Base;
virtual void operator() () { std::cout << "d"; }
};
int main()
{
Derived d(4);
std::cout << std::endl;
return 0;
}
预期结果:
dddd
实际结果(Ubuntu 14.04,gcc v4.8.2):
pure virtual method called
pure virtual method called
terminate called without an active exception
terminate called without an active exception
dAborted (core dumped)
请注意,至少曾经一次真正调用过Derived::operator()
(最后一行的d
,几乎总是这样)。
即使代码非常简单,并且几乎与原始代码相同(请参见上面的链接),它也无法工作。 我花了数小时来解决这个问题。
目标是构造具有多个线程的Derived
。 此数量的线程将在构造函数中执行并在析构函数中加入。 应该将operator()
用作线程主体函数(如原始代码中一样)。 而且,它应该是虚拟的以便提供多态性。
就我而言, run
通过*this
(由于某种原因)键入为Base
,而不是Derived
,因此线程执行纯虚拟的Base::operator()
附加问题:贴标签operator()
有什么保护的方法吗?
有人可以帮我吗? 谢谢。
编辑:
根据Billy ONeal的回答,我重新编写了代码,因此Derived
构造函数调用run
,但是没有成功
#include <thread>
#include <iostream>
#include <vector>
class Base
{
public:
virtual void run (int count) { // non-virtual does not help eighter
for (int i=0; i<count; ++i)
threads.emplace_back(std::ref(*this));
}
virtual ~Base () {
for (auto& t : threads)
t.join();
}
virtual void operator() () = 0;
protected:
std::vector< std::thread > threads;
};
class Derived : public Base
{
public:
Derived (int count) { run(count); }
virtual void operator() () { std::cout << "d"; }
};
int main()
{
Derived d(4);
std::cout << std::endl;
return 0;
}
结果随时间而变化-这就是我所拥有的
1) d
2) dd
3) ddd
4) dddd
5) d
pure virtual method called
terminate called without an active exception
ddAborted (core dumped)
特别是5)
我无法解释。
我在Derived d(4);
周围添加了{...}
Derived d(4);
作为强制在行结束程序终止之前执行析构函数的匿名块,但是从那以后,我只有
pure virtual method called
terminate called without an active exception
ddAborted (core dumped)
您的代码具有竞争条件(因此存在未定义的行为)。 在Base
的构造函数中启动线程时,线程将立即尝试在该对象上调用operator()
。 但是Derived
的构造函数尚未运行,因此operator()
仍然是Base
的构造函数,后者是纯虚拟的。 另一个有效的执行方式是Base
的构造函数和Derived
的构造函数在线程实际运行之前完成,这将提供您所期望的行为,但是结果不太可能。
您对this->run
评论this->run
因为输出抱怨调用了纯虚拟成员函数,而run
不是纯虚拟成员,只有operator()
是。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.