2009-08-14 10 views
33

Estaba comprobando el comportamiento de dynamic_cast y descubrí que cuando falla, la excepción std :: bad_cast se produce solo si el destino es un tipo de referencia. Si el destino es un tipo de puntero, entonces no se lanza ninguna excepción del elenco. Este es mi código de muestra:Diferencia de comportamiento al usar dynamic_cast con referencia y punteros

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

class B : public A 
{ 
}; 

int main() 
{ 
    A* p = new A; 

    //Using reference 
    try 
    { 
    B& b = dynamic_cast<B&>(*p); 
    } 
    catch(std::bad_cast exp) 
    { 
    std::cout<<"Caught bad cast\n"; 
    } 

    //Using pointer 
     try 
    { 
    B* pB = dynamic_cast<B*>(p); 

    if(pB == NULL) 
    { 
     std::cout<<"NULL Pointer\n"; 
    } 
    } 
    catch(std::bad_cast exp) 
    { 
    std::cout<<"Caught bad cast\n"; 
    } 

    return 0; 
} 

La salida es "Caught bad cast" y "NULL puntero". El código se compila utilizando VS2008. ¿Es este el comportamiento correcto? Si es así, ¿por qué hay una diferencia?

Respuesta

59

Sí, este es el comportamiento correcto. La razón es que puede tener un puntero nulo, pero no una referencia nula: cualquier referencia tiene que estar vinculada a un objeto.

Así que cuando dynamic_cast para un tipo de puntero falla, devuelve un puntero nulo y el llamante puede verificarlo, pero cuando falla para un tipo de referencia no puede devolver una referencia nula, por lo que una excepción es la única forma razonable para señalar un problema

5

Sí, lo es. Como dynamic_cast no puede devolver NULL para un modelo de referencia fallido, una excepción es la única salida.

Es decir, una referencia no puede ser NULA, por lo que no hay nada adecuado para devolver.

+1

Pero, ¿por qué no se puede lanzar la excepción en el caso de los punteros también? – Naveen

+1

Tendría que intentar capturar cada dynamic_cast que es código sucio. En su lugar, puede tomar la dirección, dynamic_cast y comprobar null. – sharptooth

+0

Además, arrojar y atrapar excepciones es relativamente costoso, y sospecho que los diseñadores querían encontrar una manera de minimizar ese costo. –

8

Sí, 5.2.7/9

El valor de un no echó a un tipo de puntero es el valor del puntero nulo del tipo de resultado requerido. Un lanzamiento fallido al tipo de referencia arroja bad_cast (18.5.2).

18

Véase la Norma C++, sección 5.2.7/9:

9 El valor de un elenco fallado en tipo de puntero es el valor de puntero nulo del tipo de resultado requerido. Un modelo fallido para el tipo de referencia arroja bad_cast (18.5.2).

cuanto a por qué - estas son las palabras de BS del libro & D E, sección 14.2.2:

Puedo usar un molde de referencia cuando quiero una suposición sobre un tipo de referencia controlado y regulado lo considero una falla para mi suposición es incorrecta. Si, en cambio, quiero seleccionar entre las alternativas plausibles , utilizo un molde de puntero y pruebo el resultado con .

+1

Agradezco el trabajo adicional en esta respuesta para asociar tanto la interpretación estándar como la de Stroustrup. –

Cuestiones relacionadas