2009-02-06 22 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: No se puede dynamic_cast `(& a) -> std :: auto_ptr < _TP> :: get() const¿Por qué falla este dynamic_cast de auto_ptr?

+0

¿dónde está la declaración para a :: get()? – cbrulak

Respuesta

11

Bueno, std::auto_ptr<B> no se deriva de std::auto_ptr<A>. Pero B se deriva de A. El auto_ptr no lo sabe (no es tan inteligente). Parece que quiere usar un puntero de propiedad compartida. boost::shared_ptr es lo ideal, sino que también proporciona una dynamic_pointer_cast:

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

Para auto_ptr, tal cosa no puede realmente trabajar. Porque la propiedad se moverá al b. Pero si el lanzamiento falla, b no puede obtener la propiedad. No está claro qué hacer entonces para mí. Probablemente tendrías que decir si el lanzamiento falla, y seguirá teniendo la propiedad, lo que suena a que causará serios problemas. Mejor comienzo usando shared_ptr. Tanto a y b entonces habría que apunte al mismo objeto - pero B como shared_ptr<B> y a como un dinámico reparto shared_ptr<A>

5

no funciona de esa manera. A : public B no implica auto_ptr<A> : public auto_ptr<B>. Esta es la razón por la cual shared_ptr boost proporciona shared_dynamic_cast. Se podría escribir un elenco dinámico auto_ptr sin embargo:

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; 

}

acaba de ser conscientes de lo que sucede aquí. Como el auto_ptr tiene semántica de propiedad, un downcast exitoso significa que el original más generalmente escrito, auto_ptr ya no tiene propiedad.

0

usted está tratando de lanzar un A* (devuelto por a.get()) a std::auto_ptr<B>, y dado que el segundo no es ni siquiera un tipo de puntero esta falla. Probablemente lo que desea es echarlo a B*:

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

Esto todavía no se compilará, porque A y B no son tipos polimórficos. A necesita tener una función virtual para hacer que los tipos sean polimórficos. Esto se compilará, pero el elenco lanzará std::bad_cast, ya que no es realmente un B*.

E incluso si fuera un B*, , fallará de maneras horribles si intenta usarlo. Tanto std::auto_ptr s a como b supondrán que poseen el objeto y lo liberarán más adelante, lo que provocará todo tipo de daños en la memoria. Probablemente desee utilizar a.release() después de que el lanzamiento se haya realizado correctamente.

0

Creo que C++ almacena RTTI (información de tipo de tiempo de ejecución) en el vtable. Por lo tanto, para usar dynamic_cast <> con un objeto instancia, el objeto necesita tener 'vtable'. C++ crea vtable solo cuando al menos una función se declara 'virtual' en la clase.

La clase A y la Clase B no tienen funciones virtuales. Esta podría ser la razón de la falla dynamic_cast. Intente declarar un destructor virtual en la clase base.

Cuestiones relacionadas