2013-04-29 9 views
5

Ho letto alcuni altri thread su questo sito e menzionano come dynamic_cast e static_cast siano entrambi sicuri per l'upcasting.Casting - Perché dovrei farlo per Upcasting

Perché sono necessari anche per l'upcasting?

Ad esempio, se la classe B è derivato da A, allora

A * ptr = new B(); 

funziona ancora, e si comporta come un oggetto di tipo A. (io sono anche da un ambiente Java in cui la conversione per upcasting non è necessaria.

ho anche letto su questo sito che dynamic_cast non è necessario per downcasting [in questione "When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?"] . anche in questo caso, penserei che casting è veramente solo necessario quando si sta downcasting dal upcasting avviene in modo automatico.

Dove mi sbaglio?

+0

Nota: nella domanda precedente, una delle risposte dice "Non devi usarlo per lanciare verso il basso ...". Tuttavia, dal contesto della frase completa, il significato è che non sei limitato a usarlo solo per lanciare verso il basso. [Ho modificato quella risposta per rimuovere l'ambiguità.] –

risposta

3

Se si dispone di gerarchie di ereditarietà complesse, il comportamento di upcast predefinito potrebbe non funzionare. Si consideri ad esempio:

struct A {}; 
struct B : A {}; 
struct C : A {}; 
struct D : B, C {}; 

In quella gerarchia un oggetto di tipo D ha due diverse basi di tipo A. La conversione da D* a A* è ambigua. Per questo tipo di casi è possibile forzare passare attraverso una fase intermedia

A *p = static_cast<B*>(d); // Give me the 'A' subobject within 'B' 

Allo stesso modo, se v'è una funzione con più sovraccarichi che può assumere sia la base o il tipo derivato ed è necessario chiamare la versione prendendo la base tipo (nota: codice odore qui!), quindi è possibile utilizzare il cast per dirigere la risoluzione di sovraccarico. Di nuovo, se hai bisogno di indirizzare la risoluzione di sovraccarico, probabilmente stai facendo qualcos'altro di sbagliato.

Oltre ai casi d'angolo (ad es.quando l'upcast predefinito non funziona) non c'è davvero alcun motivo per utilizzare esplicitamente un'operazione di cast, e in realtà vorrei consigliarlo, dato che i cast dovrebbero essere una spia e l'uso eccessivo potrebbe renderli normale e non generare allarmi durante la lettura codice.

+1

Un buon esempio di caso d'angolo, ma metterei in discussione la sua rilevanza pratica dal momento che questo è un codice errato che non dovrebbe mai verificarsi nella vostra base di codice (diamante della morte) - almeno in combinazione con un upcast. –

0

Perché sono necessari anche per l'upcasting?

non lo sono, e li utilizzano per upcasts è (IMHO) fuorviante: nessuna cast è necessario per un motivo: logicamente, un oggetto sottoclasse è a un'istanza della superclasse.

In sintesi, scoraggerei i reindirizzamenti espliciti. Per le persone che insistono su quel esigo coerenza almeno: utilizzare upcasts espliciti ovunque, tra cui in Inizializzazioni:

A * ptr{static_cast<A*>(new B)}; 

maggior parte delle persone saranno d'accordo che questo è solo stupido.

+0

Questo è quello che pensavo. Ma allora perché una risposta con 673 upvotes dice "Non devi usarlo per lanciare verso il basso" per le conversioni dinamiche http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast- e-reinterpretare-cast-essere-usato. Non ho postato su quel thread poiché pensavo che ci fosse qualcosa di fondamentalmente sbagliato nella mia comprensione – user929404

+1

@ user929404 Stai interpretando erroneamente quella risposta - il messaggio effettivo è che 'reinterpret_cast' fa * non solo * funziona per i downcast, ma può anche eseguire altri cast . Tuttavia, la pubblicazione non dice nulla in realtà * aver * di usarlo per gli upcast (altri commenti online, tuttavia * do * consigliare questo). –

1

In caso di ereditarietà multipla (che Java non ha realmente) è possibile regolare il puntatore "questo". In tal caso reinterpret_cast non è sicuro, che è ciò che stanno cercando di sottolineare dicendo che static_cast e dynamic_cast sono sicuri.

Come piccola nota, in un'indagine su un codebase che doveva essere portato su Android-without-dynamic_cast ho trovato 127 dynamic_cast, di cui 122 non erano effettivamente necessari. Questo è stato il codice scritto da persone che erano OK a molto abile in C++.