2010-11-09 23 views
30

Secondo this, void* non ha informazioni RTTI, pertanto il casting da void* non è legale e ha senso.dynamic_cast da "void *"

Se non ricordo male, dynamic_cast da void* funzionava su gcc.

Potete chiarire il problema.

risposta

35

dynamic_cast funziona solo sui tipi polimorfici, cioè classi contenenti funzioni virtuali.

In gcc si può dynamic_castavoid* ma non da:

struct S 
{ 
    virtual ~S() {} 
}; 

int main() 
{ 
    S* p = new S(); 
    void* v = dynamic_cast<void*>(p); 
    S* p1 = dynamic_cast<S*>(v); // gives an error 
} 
3

È vero che void* non può essere dynamically_cast da.

Probabilmente ti stai ricordando male. Con g ++ 4.5 e il seguente codice

struct A { 
    virtual ~A(); 
}; 

int main() { 
    A a; 
    void *p = &a; 
    A* pa = dynamic_cast<A*>(p); 
} 

ottengo il seguente errore:

cannot dynamic_cast 'p' (of type 'void*') to type 'struct A*' (source is not a pointer to class)

0

Credo che si confondono con dynalic_cast-void*. È legale e ottiene il puntatore all'oggetto di classe più derivato.

dynamic_castdavoid* è illegale - il tipo pressofuso da deve essere polimorfico - contiene almeno una funzione virtuale (conteggi distruttore virtuale troppo).

+0

A meno che il tipo di classe assegnato a una classe base accessibile non ambigua del tipo di classe dell'espressione casted-from, nel qual caso quest'ultimo non deve essere morfica. – usta

0

È possibile eseguire il cast di un puntatore a tipo polimorfico su void *, ma non viceversa.

11

In 5.2.7 - Dynamic cast [expr.dynamic.cast] si dice che per dynamic_cast<T>(v):

  • Se T è un tipo di puntatore, v sarà un rvalue di un puntatore per completare tipo di classe
  • Se T è un tipo di riferimento, v sarà un lvalue di un tipo di classe completo (grazie usta per commentare il mio mancante)

...

  • In caso contrario, v sarà un puntatore o un lvalue di tipo polimorfico

Quindi, no, un valore (void*) non è permesso.

Pensiamo a ciò che la vostra richiesta potrebbe significare: dicono che hai un puntatore che è davvero a un Derived1*, ma il codice dynamic_cast -ing sa solo che è un void*.Diciamo che stai provando a trasmetterlo a un Derived2*, dove entrambe le classi derivate hanno una base comune. A livello superficiale, si potrebbe pensare che tutti i puntatori puntino allo stesso oggetto Base, che conterrebbe un puntatore alla tabella di distribuzione virtuale e RTTI rilevanti, quindi tutto potrebbe bloccarsi insieme. Tuttavia, si consideri che le classi derivate possono avere più classi base, e quindi il necessario oggetto secondario della classe Base potrebbe non essere quello a cui punta Derived* - disponibile solo come void*. Non funzionerebbe. Conclusione: il compilatore deve conoscere questi tipi in modo che possa eseguire alcuni aggiustamenti ai puntatori in base ai tipi coinvolti.

 
Derived1* -----> [AnotherBase] 
       [[VDT]Base] <-- but, need a pointer to start of 
       [extra members] this sub-object for dynamic_cast 

(Alcune risposte parlano della necessità per il puntatore si sta gettando da essere di un tipo polimorfico, con funzioni virtuali. Questo è tutto valido, ma un po 'fuorviante. Come potete vedere sopra, anche se il void* è a un tal tipo che ancora non funzionerebbe in modo affidabile senza le informazioni di tipo completo, poiché il vero problema è che void* sta presumibilmente puntando all'avvio dell'oggetto derivato, mentre è necessario un puntatore all'oggetto secondario della classe base da cui deriva il cast-to type.)

+0

Se T è un tipo di puntatore, v deve essere un valore di un puntatore per completare il tipo di classe, ... Se T è un tipo di riferimento, v deve essere un lvalue di un tipo di classe completo, ... – usta

+1

@usta: fixed , Grazie. –