2015-10-28 23 views
5

Diciamo che ho tre classi: A (la madre, astratto), e B e C, i figli di A.implicita conversione vs. static_cast quando upcasting

Quindi B e C ereditare da A (eredità pubblico) . Ho un elenco di puntatori ad A, che compilo con i puntatori di B o C.

La domanda è: qual è lo stile preferito quando si esegue il casting/la conversione?

class A {}; 
class B : public A {}; 
class C : public A {}; 

B* objB = new B(); 
C* objC = new C(); 

std::list<A*> myList; 
// Option A: static cast conversion 
myList.push_back(static_cast<A*> (objB)); 
myList.push_back(static_cast<A*> (objC)); 

// Option B: implicit conversion 
myList.push_back(objB); 
myList.push_back(objC); 

// Option C: C-style conversion (I understand that this is evil and must be avoided) 
myList.push_back((A*) objB); 
myList.push_back((A*) objC); 

Quindi, in termini di chiarezza (stile del codice) e in termini di sicurezza, qual è il migliore? Capisco che static_cast è più facile da cercare, ma in questo caso, una conversione implicita dovrebbe essere sufficiente.

risposta

7

Non è necessario static_cast per la classe base, lo static_cast deve passare nell'altra direzione. Quindi questo è bene

myList.push_back(objB); 
myList.push_back(objC); 

Il tempo che avrebbe dovuto static_cast è di fare qualcosa che esprimono un A* a una classe derivata B*

B* some_obj = static_cast<B*>(myList.front()); 
+0

Questa è la risposta di cui avevo bisogno. Quindi niente static_cast quando upcasting, ma sì quando downcasting. Grazie! (e una risposta molto veloce!) – fern17

+1

@ fern17 Inoltre, si noti che quando si esegue il downcast, è possibile che non si sappia sempre se si tratta di un B o di un C. Questo è il significato di 'dynamic_cast'. – JorenHeit

+0

Sì, lo so, grazie per renderlo esplicito (per il futuro me che tornerò a questa domanda) – fern17

0

mi piacerebbe estendere sulla risposta fornita già con una soluzione molto generale.

Non trasmettere mai in modo esplicito ciò che il compilatore eseguirà già implicitamente per te.

Potremmo anche generalizzare questo seguito:

Gli esseri umani fanno errori. Non fare mai esplicitamente ciò che il compilatore farà già per te.

... anche se questo potrebbe essere un po 'più discutibile in alcuni casi eccezionali molto oscuri. La frase precedente dovrebbe sempre essere vera.

Fondere esplicitamente in modo superfluo è solo violare il principio ASCIUTTO e, cosa più importante, invitare errore umano e confusione in futuro.

Evitare quindi di trasmettere espressamente tutto ciò che non lo richiede. I lanci espliciti sono un'arma: ostentarli troppo spesso e qualcuno è destinato a farsi male.