まず第一に、このままではコードが機能しないということです。のデストラクタはbase少なくともprotected(または派生クラスがベースのフレンドである) 必要があります。privateデストラクタとは、コンパイラが派生クラスのデストラクタを記述することを許可しないことを意味します。protectedここで、デストラクタがあると仮定します... (拡張するクラスを設計する場合は、パブリック仮想デストラクタまたは保護された非仮想デストラクタのいずれかを提供してください!)
すべては の実装に依存し、SmartPointer特にstd::shared_ptr(またはブースト対応のboost::shared_ptr) はその状況をきれいに管理できます。このソリューションは、破壊目的で型のある種の部分的な型消去を実行します。基本的に、スマート ポインターには、ポインターに割り当てることができる任意のポインターを受け入れるテンプレート化されたコンストラクターがありますが、テンプレート化されているbaseため、具体的な型を認識しています。その時点でdeleter、適切なデストラクタを呼び出す合成関数が格納されます。
簡単にするために、次を使用しstd::functionます。
template <typename T>
void delete_deleter( void * p ) {
delete static_cast<T*>(p);
}
template <typename T>
class shared_pointer {
T * ptr;
std::function<void(void*)> deleter;
public:
template <typename U>
shared_pointer( U* p, std::function<void()> d = delete_deleter<U> )
: ptr(p), deleter(d)
{}
~shared_pointer() {
deleter( ptr ); // call the stored destructor
}
};
コードは展示専用です。本番用に微調整する必要があります(function参照カウントを保存する場所...)が、アイデアを与えるには十分です:オブジェクトの正確なタイプが知られている場合 (スマート ポインターを作成するとき)、必要なデストラクタの正確なバージョンを呼び出すラッパーを作成し (タイプ消去の一部を提供します)、それをそのままにしてdelete、オブジェクトが必要なときに代わりにそれを呼び出します。deleteオペレーター。
これは、代わりに特別なメソッドを呼び出す必要がある他のリソースを管理するためにも使用できますdelete。
// exhibition only!
shared_pointer<Foo> p( Factory.create(), &Factory::release );
繰り返しますが、このプロダクションの準備を整える前に、かなり多くの作業が必要です。
消去を簡素化するために使用される依存関係std::functionは、問題から排除できます。単純なケース (スマート ポインターで割り当てられたメモリnewと解放されたメモリのみdeleteがサポートされます) では、deleter基本クラスに単一の virtual を提供し、既存のクラスを現在の実装でそのオーバーライドからテンプレート化された派生クラスにoperator()(void*)リファクタリングします。一般的なケース (任意のタイプのリソースを保持する) を使用する必要がある場合は、努力する価値はありません。単にまたはを使用してください。delete_deleterdeleteroperator()(void*)std::functionboost::function