私は練習問題としてスマートポインタのコードを書いています。チュートリアルをオンラインで使用する(1、2)私はリファレンスカウントで通常のスマートポインタクラスを開発しました。問題は、私は次のことを把握することができませんです:非仮想デストラクタのオブジェクトスライシングを避ける
スマートポインタは、これ以上の言及は 特定のオブジェクトに存在しないこと、それはあっても、 元の型へのポインタを経由してオブジェクトを削除する必要があります検出されたとき最終的なスマート ポインタのテンプレート引数は基本型です。これは、非仮想デストラクタ のオブジェクトのスライスを避けるためです。
どうすれば実現できますか?基本的に私のコードは以下のようになります(チュートリアルから)。
template < typename T > class SP
{
private:
T* pData; // pointer
RC* reference; // Reference count
public:
SP() : pData(0), reference(0)
{
// Create a new reference
reference = new RC();
// Increment the reference count
reference->AddRef();
}
SP(T* pValue) : pData(pValue), reference(0)
{
// Create a new reference
reference = new RC();
// Increment the reference count
reference->AddRef();
}
SP(const SP<T>& sp) : pData(sp.pData), reference(sp.reference)
{
// Copy constructor
// Copy the data and reference pointer
// and increment the reference count
reference->AddRef();
}
~SP()
{
// Destructor
// Decrement the reference count
// if reference become zero delete the data
if(reference->Release() == 0)
{
delete pData;
delete reference;
}
}
T& operator*()
{
return *pData;
}
T* operator->()
{
return pData;
}
SP<T>& operator = (const SP<T>& sp)
{
// Assignment operator
if (this != &sp) // Avoid self assignment
{
// Decrement the old reference count
// if reference become zero delete the old data
if(reference->Release() == 0)
{
delete pData;
delete reference;
}
// Copy the data and reference pointer
// and increment the reference count
pData = sp.pData;
reference = sp.reference;
reference->AddRef();
}
return *this;
}
};
EDIT:
は、私は元の型へのポインタを持っている必要があることを達成するために。 delete via a pointer to Derived, not Baseが
しかし、今のコメントと回答を見て以来、私は両方が関係していると思う:私はここに質問を掲載している
。
template <typename T>
template <typename U>
Sptr<T>::Sptr(U* u) : obj(u),ref(NULL) {
//do something
ref = new RC();
ref->AddRef();
}
今すぐDerived
がBase1
から派生しSptr<Base1> sp(new Derived);
を考える:私はコンストラクタを持っています。 Base1はコンストラクタ/デストラクタを保護しています。 タイプT
のオブジェクトの格納先ですが、タイプUのオブジェクトに格納する必要があります。これを保持する必要があります。どうやってやるの?
基本クラスに仮想デストラクタがなく、誰かがその基本クラスへのポインタによって派生クラスを削除しようとしている場合、その人はそれを間違って実行しています。 – Chad
これを実現するには、 'SP'にテンプレートコンストラクタ' SP :: SP(U * u){...} 'を与えなければならず、何らかの形で元の型' U'( ' T')を呼び出して、後に 'U'のデストラクタを呼び出すことができます。 –
Angew
C++ 11は準拠スマートポインタがこれをしなければならないと述べていますか? 'std :: unique_ptr'は以下のようにはなりません:http://ideone.com/iyanmY – Chad