私の質問はすでにかなりよく答えられています。
しかし、人々が不思議に思った場合に備えて、私は aunique_ptr<Derived>
を a に移動できunique_ptr<Base>
、オブジェクトのデリータを記憶できるDerived
、つまり、Base
仮想デストラクタを持つ必要がない、という誤った考えを持っていました。それは間違っていました。Kerrek SB のコメントを「答え」として選択しますが、コメントに対してそれを行うことはできません。
@Howard : 以下のコードは、動的に割り当てられたデリータのコストがすぐにサポートされることを意味する必要があると私が信じていたことを達成する 1 つの方法を示していunique_ptr
ます。
#include <iostream>
#include <memory> // std::unique_ptr
#include <functional> // function
#include <utility> // move
#include <string>
using namespace std;
class Base
{
public:
Base() { cout << "Base:<init>" << endl; }
~Base() { cout << "Base::<destroy>" << endl; }
virtual string message() const { return "Message from Base!"; }
};
class Derived
: public Base
{
public:
Derived() { cout << "Derived::<init>" << endl; }
~Derived() { cout << "Derived::<destroy>" << endl; }
virtual string message() const { return "Message from Derived!"; }
};
class BoundDeleter
{
private:
typedef void (*DeleteFunc)( void* p );
DeleteFunc deleteFunc_;
void* pObject_;
template< class Type >
static void deleteFuncImpl( void* p )
{
delete static_cast< Type* >( p );
}
public:
template< class Type >
BoundDeleter( Type* pObject )
: deleteFunc_( &deleteFuncImpl< Type > )
, pObject_( pObject )
{}
BoundDeleter( BoundDeleter&& other )
: deleteFunc_( move( other.deleteFunc_ ) )
, pObject_( move( other.pObject_ ) )
{}
void operator() (void*) const
{
deleteFunc_( pObject_ );
}
};
template< class Type >
class SafeCleanupUniquePtr
: protected unique_ptr< Type, BoundDeleter >
{
public:
typedef unique_ptr< Type, BoundDeleter > Base;
using Base::operator->;
using Base::operator*;
template< class ActualType >
SafeCleanupUniquePtr( ActualType* p )
: Base( p, BoundDeleter( p ) )
{}
template< class Other >
SafeCleanupUniquePtr( SafeCleanupUniquePtr< Other >&& other )
: Base( move( other ) )
{}
};
int main()
{
SafeCleanupUniquePtr< Base > p( new Derived );
cout << p->message() << endl;
}