作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试实现多态性,其中派生类实现一个在单独线程中运行的方法:
#include <memory>
#include <thread>
#include <chrono>
class Base
{
public:
std::thread m_jobThread;
~Base() { if (m_jobThread.joinable()) m_jobThread.join(); }
virtual void doJob() = 0;
void doJobInBackground() { m_jobThread = std::thread(&Base::doJob, this); }
};
class Drived : public Base
{
public:
Drived() = default;
virtual void doJob() final { std::this_thread::sleep_for(std::chrono::seconds(1)); }
};
int main(int argc, char const *argv[])
{
Drived d;
d.doJobInBackground();
return 0;
}
如何在没有纯虚方法调用
异常的情况下安全地实现这一点?
我希望能够在作业进行时销毁派生对象,并让基类的析构函数处理线程管理。但是由于派生类的 vtable 在基类的析构函数运行之前被销毁,我得到一个纯虚方法异常。
我想在派生类的析构函数中添加一个 stop
方法,以确保线程已连接。但这违背了我的多态设计的目的,我希望派生类只负责定义 doJob
方法,而不直接或间接处理线程等基类的资源。 ..
如果这可能的话,有什么想法吗?我需要更改设计吗?
最佳答案
正如 Sam Varshavchik 在他上面的评论中所指出的,您在这里触发纯虚函数调用的原因是 d
的析构函数在您的第二个线程开始执行之前就已运行。您只在 Base
析构函数中进行同步。然而,当 Base
析构函数运行时,对象的 Derived
部分已经被销毁。此时对象的动态类型只是 Base
,因为这是仍然存在的所有类型,因此,虚函数调用分派(dispatch)到纯基础版本。严格来说,您实际上在这里有未定义的行为,因为对象在一个线程中被销毁而另一个线程可能正在调用它的方法违反了 [basic.life]/7.2 .当析构函数调用开始时,对象的生命周期结束 [basic.life]/1.3 ,第二个线程中的方法调用不inter-thread happen before第一个线程中的析构函数调用......
只是
#include <thread>
#include <chrono>
class Base
{
std::thread m_jobThread;
public:
void join() { if (m_jobThread.joinable()) m_jobThread.join(); }
virtual void doJob() = 0;
void doJobInBackground() { join(); m_jobThread = std::thread(&Base::doJob, this); }
};
class Derived : public Base
{
public:
virtual void doJob() final { std::this_thread::sleep_for(std::chrono::seconds(1)); }
};
int main(int argc, char const* argv[])
{
Derived d;
d.doJobInBackground();
d.join();
return 0;
}
工作正常......
关于c++ - 如何用多态管理线程资源? (C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55912946/
我是一名优秀的程序员,十分优秀!