私は次の問題で箱の外で考えるのに苦労しています。クラス階層があります:
[BaseClass] --> [Win32Class]
[BaseClass] --> [LinuxClass]
[BaseClass] --> [VxWorksClass]
実装クラスは、APIレベルの関数を呼び出します。これらは、基本クラスの純粋仮想関数内で実行されます。
これで、ユーザーがオブジェクトを作成、使用、および終了したら、Done
(基本クラスから)関数を呼び出す必要があります。これにより、クリーンアップとリソースの割り当て解除が行われます。このクリーンアップの一部は、いくつかのAPIレベルの関数を呼び出すことです。これらは当然、基本クラスの純粋な仮想であり、派生クラスに実装されます。ここまでは順調ですね。
ここに問題があります。ユーザーが明示的に呼び出さDone
ないと、リソースが適切に解放されないためにさまざまなメモリリークが発生します。だから、私はそれを簡単にして、破壊時の自動クリーンアップDone
から電話をかけると思いました。~BaseClass()
まあ、それほど多くはありません。これらの純粋な仮想を呼び出すのでDone
、すべての地獄は解き放たれます。
この問題を回避するためにこれを再設計する方法について何か考えはありますか?
サンプルコード
class BaseClass{
virtual ~BaseClass(){
Done();
}
void Done(){
// A bunch of OS-independent clean-up logic
Cleanup();
// some more OS-independent clean-up logic
}
virtual void Cleanup() = 0;
};
class Win32Class : public BaseClass{
virtual void Cleanup(){
// call some Win32-specific cleanup code
}
};
class LinuxClass : public BaseClass{
virtual void Cleanup(){
// call some Linux-specific cleanup code
}
};
==========================================これ
が私の解決策です。ラッパークラスを使用します。またはDone
のデストラクタを呼び出さないでくださいWin32Class
BaseClass
class Win32Wrapper{
public:
Win32Class* object_;
public:
Win32Wrapper(){
this->object_ = new Win32Class;
}
~Win32Wrapper(){
this->object_->Done();
delete this->object_;
}
};
==デストラクタで純粋な仮想を呼び出す方法==
class Base{
public:
Base(){
}
virtual ~Base(){
Done();
}
void Done(){
Clean();
}
virtual void Clean() = 0;
};
class Derived : public Base{
public:
Derived(){
}
~Derived(){
}
virtual void Clean(){
}
};
コンパイラはでPFVの呼び出しについて文句を言わないので、ユーザーはプログラムが機能すると思いますBase::Done()
。