バックグラウンドスレッドを開始できるベースクラスがあり、必要なときに停止します。そのスレッドは、2つの仮想メソッド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
私は 'スタート()'コンストラクタと 'ストップ(中)を呼び出すと'デストラクタで出力は次のようになります。 –
近い 継承オープン 基本実際に基本クラス 'Close'と' Open'は、仮想的に純粋です。そして、私がBaseクラスのデストラクタで 'Stop()'を呼び出すと、プログラムは 'Pure virtual method called'エラーでクラッシュします。 –