我有一個基類可以啓動後臺線程,並在需要時停止它。該線程調用兩個虛擬方法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'錯誤 –