2009-02-26 17 views
5

Tengo una clase base y una clase derivada. Cada clase tiene un archivo .h y un archivo .cpp.dynamic_cast failed

que estoy haciendo moldeado dinámico del objeto de la clase base para la clase derivada en el siguiente código:

archivos h:

class Base 
{ 
    public: 
    Base(); 
    virtual ~Base(); 
}; 

class Derived : public Base 
{ 
    public: 
    Derived(){}; 
    void foo(); 
}; 

class Another 
{ 
    public: 
    Another(){}; 
    void bar(Base* pointerToBaseObject); 
}; 

cpp:

Base::Base() 
{ 
    //do something.... 
} 
Base::~Base() 
{ 
    //do something.... 
} 
void Derived::foo() 
{ 
    Another a; 
    a.bar(this); 
} 
void Another::bar(Base* pointerToBaseObject) 
{ 
    dynamic_cast<Derived*>(pointerToBaseObject) 
} 

de alguna extraña razón , el lanzamiento falla (devuelve NULL). Sin embargo, la conversión tiene éxito si muevo la implementación del constructor de la clase Derivada de .h al archivo .cpp.

¿Qué puede causarlo?

El compilador es gcc 3.1, en Linux-SUSE. Por cierto, veo este comportamiento solo en esta plataforma, y ​​el mismo código funciona bien en Visual Studio.

+0

tal vez es un error con gcc 3.1? prueba la opción "-fdump-class-hierarchy" y mira si crea un vtable para tus dos clases –

Respuesta

5

El código, tal como se publicó, no debería fallar, siempre que tenga una función virtual en la clase base (como lo indicó litb).

Pero creo que cada compilador actual genera un tipo de error de "clase base no es polimórfica" si no lo hubiera hecho, por lo que probablemente no sea el problema.

Lo único que se me ocurre es que, debido a algún error extraño, todo se inline y no se genera vtable. Pero si coloca el constructor en el archivo C++, el compilador decide no incluir todo, lo que desencadena la creación de un vtable, haciendo que su conversión funcione.

Pero esto son conjeturas muy salvaje, y no creo que cualquier compilador tendría un error tan en ella (?)

Si desea una respuesta definitiva, publicar más código. Y el compilador/plataforma utilizada.

EDIT: Al ver el código actualizado

Creo que al menos debe derivar derivando desde la Base;) (supongo que es un error tipográfico)

Pero después de ver el código, lo único que puede pensar es que gcc (erróneamente) lo engloba todo y no genera un vtable para Derived. Por lo que vale, esto funciona bien compilado con gcc 4.0

3.1 tiene más de 7 años de edad en este momento ... si hay alguna posibilidad de actualizar iría por ello.

7

¿Tiene alguna función virtual en la Base? No funcionará de otra manera. Si nada más, haz que su controlador sea virtual.

No sé si ya lo había preguntado el otro chico que borró su respuesta, pero creo que fue algo diferente: ¿Estás haciendo el dynamic_cast del constructor de las bases? Si es así, eso no funcionará. El compilador pensará que Base es el tipo más derivado, similar a cuando llamas a una función virtual y termina llamando a la versión de Base.

+0

Tengo funciones virtuales en Base. –

3

Haga que el destructor sea virtual y colóquelo (o al menos un método virtual) en el archivo .cpp.

Algunos compiladores (léase: gcc) buscan el primer cuerpo de método virtual no en línea encontrado y lo utilizan para decidir dónde colocar la tabla de método virtual.Si no tiene ningún método virtual con cuerpos en un archivo .cpp, la tabla de métodos virtuales no se crea.

Debe tener al menos un método virtual para que dynamic_cast funcione. El lanzamiento dinámico usa la tabla para averiguar la información del tipo, y no se crea ninguna tabla si no hay métodos virtuales.

Si tiene una clase que espera que se subclassed y tiene un destructor o si la clase tiene cualquier variable de instancia que son clases con destructores, realmente querrá hacer su destructor virtual (incluso si tiene un cuerpo vacío). De lo contrario, la limpieza que espera no ocurrirá para instancias de subclase.

0

¿Estás haciendo esto en Visual C++? Creo que solía tener que habilitar la información del tipo de tiempo de ejecución (RTTI) en la configuración del compilador para que esto funcione.

Por favor no me llame si tengo este error. ¡Ha pasado un tiempo desde que usé C++!

0

Al mirar su código, no veo ninguna herencia. ¿Olvidaste hacer eso? Derived no se deriva de nada.

0

En el código que ha publicado Derived no se deriva de Base.

Editar: FYI, código modificado funciona bien con g ++ 3.4.5