2013-05-16 12 views

risposta

10

Sia la costante nullptr (che è di tipo nullptr_t) e la costante 0 sarà implicitamente convertire al valore nullo di qualsiasi tipo di puntatore. Quindi confrontarsi con uno funzionerà ed è tecnicamente OK. A proposito, questo significa che dynamic_cast non restituisce nessuno, restituisce il valore null per il particolare tipo di puntatore.

Probabilmente è meglio prendere l'abitudine di usare nullptr anziché 0. Per quanto ne so, è davvero necessario solo per una corretta risoluzione di sovraccarico (ad esempio un sovraccarico richiede int e un altro richiede char*). Per coerenza, evitare 0 sarà il migliore.

Cosa intendo per "valore null di un tipo di puntatore"?

Considerare una variabile char * ptr. Il suo tipo è (non sorprendentemente) char *. Ma il tipo di nullptr è il tipo speciale nullptr_t. Così, quando si scrive qualcosa di simile ptr = nullptr, alcune cose tecniche devono accadere

  1. nullptr deve essere convertito in modo implicito char *.
  2. Il risultato di questa conversione viene impostato come nuovo valore di ptr.

Il valore nullo per char * è il risultato della conversione nullptr a char *. Concettualmente, è ancora nullptr, ma con un tipo diverso (char *). Questo valore nullo è diverso dal valore nullo di int * o string * o qualsiasi altro tipo di puntatore. Tendiamo a pensare a questi valori nulli semplicemente come nullptr (o 0), ma ognuno di questi è davvero un valore distinto da un tipo diverso. (A proposito, la stessa conversione avviene per il confronto usando ==).

Anche se questo può sembrare dettagli pelo nell'uovo, è molto importante nella risoluzione di sovraccarico:

void foo(char * ptr) { ... } 
void foo(int i) { ... } 
void foo(nullptr_t ptr) { ... } 

int main() 
{ 
    foo(0); // Calls void foo(int), since 0 is an int 
    foo(nullptr); // Calls void foo(nullptr_t), since nullptr is a nullptr_t 
    foo(new char('c')); // Calls void foo(char *), since new char('c') is a char* 
} 

o quando si assegnano non correlati valori nulli:

char * c_ptr = nullptr; // Okay 
int * i_ptr1 = nullptr; // Okay 
int * i_ptr2 = c_ptr; // COMPILER ERROR HERE 
+0

Puoi definire cosa intendi per il valore nullo di un tipo di puntatore? Com'è diverso da 0 o nullptr? – Patrick

+0

@Patrick: Piuttosto che rispondere a questo in un commento, lo aggiungerò alla mia risposta. Penso che sia abbastanza pertinente alla domanda. –

+0

Interessante. Quindi, quando faccio 'if (nullptr == dynamic_cast (p))', è 'nullptr' prima convertito al valore nullo di' foo * ', e quindi il confronto è fatto? – Patrick

5

Valutare il risultato in un contesto booleano:

Base * p = get(); 

if (Derived * q = dynamic_cast<Derived *>(p)) 
{ 
    q->derived_method(); 
} 
else 
{ 
    // *p isn't of type Derived 
} 

(. Questo funziona in qualsiasi versione di C++)

+0

mi piace la vostra soluzione, ma Ken Wayne più direttamente risposto la mia domanda, quindi segnalo come risposta. Grazie per la tua risposta! – Patrick

+0

Questa è probabilmente la forma migliore da usare (anche se "nullptr" è sempre esistito), dal momento che funziona per più di semplici tipi che si confrontano con 'nullptr'.Funziona per qualsiasi tipo che abbia una nozione di vuoto, espressa come una conversione a 'bool', come' facoltativo '. Penso inoltre che sia più gradevole per tipi come 'std :: function', che sono paragonabili a' nullptr', ma che non sono in realtà dei tipi di puntatore! –