2009-02-26 24 views
5

Ho una classe base e una classe derivata. Ogni classe ha un file .h e un file .cpp.dynamic_cast failed

sto facendo dynamic_cast dell'oggetto classe base alla classe derivata nel codice seguente:

h file:

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

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

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

file 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) 
} 

da qualche strana ragione , la trasmissione non riesce (restituisce NULL). Tuttavia, il casting ha esito positivo se sposto l'implementazione del costruttore della classe Derived da .h al file .cpp.

Cosa può causare?

Il compilatore è gcc 3.1, su Linux-SUSE. A proposito, vedo questo comportamento solo su questa piattaforma e lo stesso codice funziona bene in Visual Studio.

+0

forse è un bug con gcc 3.1? prova l'opzione "-fdump-class-hierarchy" e controlla se crea un vtable per le tue due classi –

risposta

5

Il codice, come pubblicato, non dovrebbe fallire, purché si disponga di una funzione virtuale nella classe base (come indicato da Litb).

Ma credo che ogni compilatore corrente generi un tipo di errore "Base class is non polymorphic" se non l'avessi, quindi probabilmente non sarà il problema.

L'unica cosa che posso pensare è che a causa di qualche bizzarro bug tutto viene sottolineato e non viene generato alcun vtable. Ma se metti il ​​costruttore nel file C++, il compilatore decide di non allineare tutto, innescando la creazione di un vtable, facendo funzionare il tuo cast.

Ma questa è solo una congettura molto selvaggia, e non credo che qualsiasi compilatore avrebbe un simile errore in esso (?)

Se si vuole una risposta definitiva, inviare più codice. E il compilatore/piattaforma utilizzata.

EDIT: Vedendo il codice aggiornato

Credo che si dovrebbe almeno derivano Derivato dalla Base;) (suppongo che sia un errore di battitura)

Ma dopo aver visto il codice, l'unica cosa che mi viene in mente è che gcc (erroneamente) inline tutto e non genera un vtable per Derived. Per quello che vale, questo funziona bene compilato con gcc 4.0

3.1 ha più di 7 anni ormai ... se c'è qualche possibilità di aggiornamento mi piacerebbe farlo.

7

Avete qualche funzione virtuale in Base? Non funzionerà diversamente. Se non altro, rendi il suo dvd virtuale.

Non so se è stato già chiesto dall'altro ragazzo che ha cancellato la sua risposta, ma credo che fosse qualcosa di diverso: stai facendo il dynamic_cast dal costruttore delle basi? Se è così, non funzionerà. Il compilatore penserà che la Base sia il tipo più derivato, simile a quando chiamate una funzione virtuale e finisce per chiamare la versione della Base.

+0

Ho funzioni virtuali in Base. –

3

Rendi virtuale il distruttore e posizionalo (o almeno un metodo virtuale) nel file .cpp.

Alcuni compilatori (leggi: gcc) cercano il corpo del metodo virtuale non integrato prima incontrato e lo usano per decidere dove posizionare la tabella del metodo virtuale.Se non si hanno metodi virtuali con corpi in un file .cpp, la tabella del metodo virtuale non viene creata.

È necessario disporre almeno di un metodo virtuale per dynamic_cast per funzionare. Il cast dinamico usa la tabella per capire le informazioni sul tipo e nessuna tabella viene creata se non ci sono metodi virtuali.

Se si dispone di una classe che si prevede di essere sottoclasse e che ha un distruttore o se la classe ha variabili di istanza che sono classi con distruttori, allora si vorrà veramente rendere virtuale il distruttore (anche se ha un corpo vuoto). Altrimenti la pulizia che ci si aspetta non si verificherà per le istanze di sottoclassi.

0

Stai facendo questo in Visual C++? Penso che sia necessario abilitare le informazioni sul tipo di runtime (RTTI) nelle impostazioni del compilatore affinché funzioni.

Per favore non scottarmi se ho sbagliato. È passato un po 'di tempo da quando ho usato C++ !!!

0

Osservando il tuo codice, non vedo alcuna eredità. Ti sei dimenticato di farlo? Derivato non è derivato da nulla.

0

Nel codice che hai pubblicato Derivato non è derivato da Base.

Edit: FYI, codice modificato funziona bene con g ++ 3.4.5