2010-10-13 3 views
5

Ich benutze C++. C++ 0x verwendet Visual Studio 2010, um korrekt zu sein.Wie verhalten sich nicht intrusive Smartpointer in Bezug auf Vererbung und Mehrfachvererbung?

Angenommen, ich habe eine Klasse Z. Um es in meiner Anwendung sicherer zu machen, mit Zeigern zu dieser Klasse zu arbeiten, kann ich konsequent Smartpointer (Shared Pointer, Weak Pointer) verwenden.

Nun ist diese Klasse Z aus einer Klasse X. erbt werden mit Zeigern auf Klasse X Einige Teile meiner Anwendung arbeiten, mit Zeigern auf Klasse Z. andere werden

  • Kann ich intelligenten Zeiger noch verwenden arbeiten?
  • Funktionieren geteilte Zeiger immer noch, wenn ich einige habe, die sich auf X beziehen, und andere, die sich auf Z beziehen? Ist sichergestellt, dass die Zerstörung des letzten gemeinsamen Zeigers auf die Instanz (egal ob std::shared_ptr<X> oder std::shared_ptr<Z>) die Instanz löscht? Bin ich sicher, dass wenn ich std::shared_ptr<X> lösche, dass die Instanz so lange gehalten wird, wie es noch eine std::shared_ptr<Y> gibt?

Nehmen wir nun an, dass ich die Mehrfachvererbung verwenden, wobei Z von Klassen X und Y. erbt Einige Teile meiner Anmeldung wird std::shared_ptr<Z> mit std::shared_ptr<X>, andere mit std::shared_ptr<Y> und andere arbeiten.

  • Kann ich weiterhin geteilte Zeiger auf diese Weise verwenden?
  • Ist immer noch gewährleistet, dass nur der letzte Smart Pointer (unabhängig davon, ob er auf X, Y oder Z zeigt) die Instanz löscht?

Übrigens, wie kann ich sicher einen intelligenten Zeiger zu einem anderen, z. Besetzung std::shared_ptr<Z> bis std::shared_ptr<X>? Funktioniert das? Ist das erlaubt?

Beachten Sie, dass ich explizit auf non-intrusive Zeiger (wie die neuen std::shared_ptr und std::weak_ptr in C++ 0x) verweisen. Bei Verwendung von intrusiven Zeigern (wie in Boost) funktioniert es wahrscheinlich, da die Instanz selbst dafür verantwortlich ist, den Zähler beizubehalten.

Antwort

6

Ja, dies wird vom Standard unterstützt, §20.9.11.2.10 [util.smartptr.shared.cast].

Die utils Sie benötigen, sind:

  • std::static_pointer_cast<>()
  • std::dynamic_pointer_cast<>()

Sie die gleiche Semantik wie ihre C++ 03 Gegenteile static_cast<>() und dynamic_cast<>() haben. Der einzige Unterschied ist, dass sie nur an std::shared_ptr s arbeiten. Und nur um dies zu tun, machen sie das, was Sie erwarten, und teilen den Referenzzähler zwischen dem Original und dem neu gedrehten shared_ptr s korrekt.

struct X { virtual ~X(){} }; 
struct Y : public X {}; 
struct Z : public X {}; 

int main() 
{ 
    { 
     //C++03 
     X* x = new Z; 
     Z* z = dynamic_cast<Z*>(x); 
     assert(z); 
     x = new Y; 
     z = dynamic_cast<Z*>(x); 
     assert(!z); 
     z = static_cast<Z*>(x); 
     assert(z); //EVIL!!! 
    } 

    { 
     //C++0x 
     std::shared_ptr<X> x{new Z}; 
     std::shared_ptr<Z> z{std::dynamic_pointer_cast<Z>(x)}; 
     assert(z); 
     x = std::make_shared<Y>(); 
     z = std::dynamic_pointer_cast<Z>(x); 
     assert(!z); 
     z = std::static_pointer_cast<Z>(x); 
     assert(z); //EVIL!!! 

     // reference counts work as expected. 
     std::shared_ptr<Y> y{std::static_pointer_cast<Y>(x)}; 
     assert(y); 

     std::weak_ptr<Y> w{y}; 
     assert(w.expired()); 

     y.reset(); 
     assert(w.expired()); 

     x.reset(); 
     assert(!w.expired());  
    } 
    { 
     //s'more nice shared_ptr features 
     auto z = std::make_shared<X>(); 
     std::shared_ptr<X> x{z}; 
     assert(z == x); 
     x = z; //assignment also works. 
    } 
} 
+0

Wow nie davon gehört ... O__o Nein in jeder Ressource zu dieser Referenz ich auf C++ 0x anders als die (indigest) Entwurf finden konnte ... – Klaim

+0

ich die Modelle sicher wissen nicht Wo, bis ich nachgesehen habe. Ich habe jedoch stark vermutet, dass sie dort waren, da sie Teil der ursprünglichen Boost.Smartptr-Bibliothek waren. –

+0

Bitte entfernen Sie "Std ::" vor den integrierten Cast-Operatoren.Ein dynamischer Cast dieses Typs erfordert außerdem polymorphe Klassen. Ihre Beispielklassen sind nicht polymorph. – sellibitze