Ich schreibe Code für Smartpointer als Übung. Tutorials online verwenden (1, 2) Ich habe eine normale Smart-Pointer-Klasse mit Referenzzählung entwickelt. Das Problem ist, ich bin nicht in der Lage die folgenden herauszufinden:Vermeiden Objekt Slicing für nicht-virtuelle Destruktoren
, wenn der Smart-Pointer erkennt, dass keine weiteren Hinweise auf ein bestimmtes Objekt vorhanden ist, muss er das Objekt über einen Zeiger auf den ursprünglichen Typen löschen, auch wenn Das Template-Argument des letzten intelligenten Zeigers ist vom Basistyp. Dies dient dazu, Objekt-Slicing für nicht-virtuelle Destruktoren zu vermeiden.
Wie kann ich das erreichen? Grundsätzlich sieht mein Code wie folgt aus (aus dem Tutorial).
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:
Um das zu erreichen, dass ich einen Zeiger auf den ursprünglichen Typ haben müssen.
ich eine Frage hier gepostet haben: delete via a pointer to Derived, not Base
Aber jetzt, da die Kommentare und Antworten sehen glaube ich, beide bezogen sind. Ich habe den Konstruktor:
template <typename T>
template <typename U>
Sptr<T>::Sptr(U* u) : obj(u),ref(NULL) {
//do something
ref = new RC();
ref->AddRef();
}
Betrachten wir nun Sptr<Base1> sp(new Derived);
wo Derived
von Base1
stammt. Base1 hat einen geschützten Konstruktor/Destruktor. Welche speichert für ein Objekt vom Typ T
Aber ich muss es durch ein Objekt des Typs U speichern. Ich muss das bewahren. Wie kann ich das machen?
Wenn eine Basisklasse keinen virtuellen Destruktor hat und jemand versucht, eine abgeleitete Klasse durch einen Zeiger auf diese Basisklasse zu löschen, macht das jemand falsch. – Chad
Um dies zu erreichen, müssen Sie 'SP' einen Template-Konstruktor' SP :: SP (U * u) {...} 'geben und irgendwie den ursprünglichen Typ' U' speichern (der von 'abgeleitet werden muss T'), um später 'U's Destruktor aufrufen zu können. –
Angew
Gibt das C++ 11 an, dass ein kompatibler intelligenter Zeiger das tun muss? Es scheint, dass 'std :: unique_ptr' nicht: http://ideone.com/iyanmY – Chad