基于C++ polymorphism with variadic function parameter,我尝试编写类似的(非模板,带构造函数)程序
代码:
#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);
作为匿名块,以在行结束程序终止之前强制执行析构函数,但是从那以后,我只有pure virtual method called
terminate called without an active exception
ddAborted (core dumped)
最佳答案
您的代码具有竞争条件(因此有未定义的行为)。当您在Base
的构造函数中启动线程时,该线程将立即尝试在该对象上调用operator()
。但是Derived
的构造函数尚未运行,因此operator()
仍然是Base
的构造函数,后者是纯虚拟的。另一个有效的执行方式是Base
的构造函数和Derived
的构造函数在线程实际运行之前完成,这将提供您所期望的行为,但是结果不太可能。
您对this->run
的评论无济于事,因为输出提示调用了纯虚拟成员函数,并且run
不是纯虚拟成员,只有operator()
是。
关于c++ - 使用std::thread时c++ 11意外的多态行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23434201/