2009-02-06 5 views
6
#include "iostream" 

    class A { 
     private: 
     int a; 
     public : 

     A(): a(-1) {} 
     int getA() { 
      return a; 
     } 

    }; 

    class A; 

    class B : public A { 
     private: 
     int b; 
     public: 

     B() : b(-1) {} 

     int getB() { 
      return b; 
     } 

    }; 

    int main() { 
     std::auto_ptr<A> a = new A(); 

     std::auto_ptr<B> b = dynamic_cast<std::auto_ptr<B> > (a); 

     return 0; 

    } 

ERROR: nicht dynamic_cast `(& a) -> std :: auto_ptr < _TP> :: get() constWarum schlägt dieser dynamic_cast von auto_ptr fehl?

+0

Wo ist die Deklaration für a :: get()? – cbrulak

Antwort

11

Nun wird std::auto_ptr<B> nicht von std::auto_ptr<A> abgeleitet. Aber B ist von A abgeleitet. Das auto_ptr weiß das nicht (es ist nicht so clever). Scheint so, als ob Sie einen geteilten Besitzzeiger verwenden möchten. boost::shared_ptr ist ideal, es bietet auch eine dynamic_pointer_cast:

boost::shared_ptr<A> a = new A(); 
boost::shared_ptr<B> b = dynamic_pointer_cast<B> (a); 

Für auto_ptr, so etwas kann nicht wirklich funktionieren. Weil sich das Eigentum zu b bewegt. Wenn die Umwandlung fehlschlägt, kann b keine Eigentumsrechte erhalten. Es ist nicht klar, was ich dann tun soll. Sie würden wahrscheinlich sagen müssen, wenn die Besetzung fehlschlägt, wird ein Besitz behalten - was klingt, als würde es ernsthafte Probleme verursachen. Am besten beginnen Sie mit shared_ptr. Sowohl a und b dann auf das gleiche Objekt zeigen würden - aber B als shared_ptr<B> und a als shared_ptr<A>

1

Der Grund dafür ist, dass auto_ptr ist nicht wirklich ein Zeiger. Es ist ein intelligenter Zeiger, der ein Zeiger-Wrapper ist, aber kein Zeiger. Der Typ, der als Template-Style-Argument an dynamic_cast übergeben wird, muss ein echter Zeiger- (oder Referenz-) Typ sein.

http://msdn.microsoft.com/en-us/library/cby9kycs(VS.80).aspx

5

dynamische Umwandlung funktioniert nicht auf diese Art und Weise. bedeutet nicht auto_ptr<A> : public auto_ptr<B>. Dies ist, warum Boost shared_ptr bietet shared_dynamic_cast. Sie könnten eine auto_ptr dynamische Umwandlung obwohl schreiben:

template<typename R, typename T> 
std::auto_ptr<R> auto_ptr_dynamic_cast(std::auto_ptr<T>& in) { 
    auto_ptr<R> rv; 
    R* p; 
    if(p = dynamic_cast<R*>(in.get())) { 
     in.release(); 
     rv = p; 
    } 
    return rv; 

}

einfach bewusst sein, was hier passiert. Seit auto_ptr s Eigentums-Semantik haben, bedeutet eine erfolgreiche Downcast das Original allgemeiner getippt, Auto_ptr nicht mehr Besitz.

0

Sie versuchen, eine A* (zurückgegeben von a.get()) an std::auto_ptr<B> zu übertragen, und da die zweite nicht einmal ein Zeigertyp ist, schlägt dies fehl. Wahrscheinlich wollen Sie es nur B* werfen:

std::auto_ptr<A> a(new A()); 
std::auto_ptr<B> b(dynamic_cast<B*>(a.get())); 

Dies wird noch nicht kompilieren, weil A und B sind nicht polymorph-Typen. A benötigt eine virtuelle Funktion, um die Typen polymorph zu machen. Dies wird kompiliert, aber der Cast wird nur std::bad_cast werfen, da es nicht wirklich ein B* ist.

Und auch wenn es ein B*, wäre, wird es auf schreckliche Weise scheitern, wenn Sie versuchen, es zu verwenden. Sowohl std::auto_ptr s a als auch b gehen davon aus, dass sie das Objekt besitzen und es später freigeben, was zu allerlei Speicherbeschädigungen führt. Sie möchten wahrscheinlich a.release() verwenden, nachdem die Besetzung erfolgreich war.

0

Ich denke, C++ speichert RTTI (Laufzeittyp Informationen) in der Vtable. Um also dynamic_cast <> mit einem Instanzobjekt zu verwenden, muss das Objekt 'vtable' haben. C++ erstellt vtable nur, wenn mindestens eine Funktion in der Klasse als "virtuell" deklariert ist.

Die Klasse A und Klasse B gibt es keine virtuellen Funktionen. Dies könnte ein Grund für den Ausfall von dynamic_cast sein. Versuchen Sie, einen virtuellen Destruktor in der Basisklasse zu deklarieren.