我有一个基类可以启动后台线程,并在需要时停止它。该线程调用两个虚拟方法Open()
和Close()
。所以所有继承的类都可以重新实现这个方法,但不能启动/停止线程例程(比示例更困难)。我想遵循RAII原则,并在基类的构造函数/析构函数中启动/停止线程。继承,后台线程和RAII
问题是,在构造函数/析构函数中调用虚拟方法是一种不好的做法,在我的情况下不起作用。 这里是我的问题的出手例如:
#include <iostream>
#include <thread>
#include <atomic>
class Base {
public:
Base() {
bg_thread_ = std::thread([this] {
Open();
while(!is_stop_) {
// do stuff
}
Close();
});
}
~Base() {
is_stop_ = true;
if(bg_thread_.joinable()) {
bg_thread_.join();
}
}
private:
virtual void Open() {
std::cout << "Base open" << std::endl;
}
virtual void Close() {
std::cout << "Base close" << std::endl;
}
std::thread bg_thread_;
std::atomic<bool> is_stop_{false};
};
class Inherited : public Base {
virtual void Open() override {
std::cout << "Inherited open" << std::endl;
}
virtual void Close() override {
std::cout << "Inherited close" << std::endl;
}
};
int main() {
Inherited inherited;
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0;
}
输出是:
Inherited open
Base close
而且不睡觉是:
Base open
Base close
我目前的做法是调用构造函数之后Start()
方法并在析构函数之前使用Stop()
,但我想要使用RAII解决方案。
void Start() {
bg_thread_ = std::thread([this] {
Open();
while(!is_stop_) {
// do stuff
}
Close();
});
}
void Stop() {
is_stop_ = true;
if(bg_thread_.joinable()) {
bg_thread_.join();
}
}
你可以在析构函数里调用'Stop()',你应该是安全的。 – rozina
如果我在构造函数中调用'Start()'而在析构函数中调用Stop(),则输出将为: 继承的开放 基本关闭 –
实际上,基类“Close”和“Open”是纯虚拟的。如果我在基类析构函数中调用'Stop()',程序将会崩溃,使用'Pure virtual method called'错误 –