2009-08-14 4 views
33

Je vérifiais le comportement de dynamic_cast et j'ai trouvé qu'en cas d'échec, l'exception std :: bad_cast n'est levée que si la destination est un type de référence. Si la destination est un type de pointeur, aucune exception n'est générée par la distribution. Voici mon exemple de code:Différence de comportement lors de l'utilisation de dynamic_cast avec référence et pointeurs

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 sortie est "Caught Bad Cast" et "Pointeur NULL". Le code est compilé en utilisant VS2008. Est-ce le bon comportement? Si oui, alors pourquoi y a-t-il une différence?

Répondre

59

Oui, ce comportement est correct. La raison en est que vous pouvez avoir un pointeur nul, mais pas une référence nulle - toute référence doit être liée à un objet. Donc, quand dynamic_cast pour un type de pointeur échoue, il retourne un pointeur nul et l'appelant peut vérifier cela, mais quand il échoue pour un type de référence, il ne peut pas retourner une référence nulle, donc une exception est la seule façon raisonnable signaler un problème.

5

Oui, c'est. Parce que dynamic_cast ne peut pas renvoyer NULL pour un cast de référence ayant échoué, une exception est la seule issue. En d'autres termes, une référence ne peut pas être NULL, donc il n'y a rien de convenable à retourner.

+1

Mais pourquoi l'exception ne peut-elle pas être levée en cas de pointeurs? – Naveen

+1

Vous devrez alors essayer de récupérer chaque dynamic_cast qui est du code corrompu. Au lieu de cela, vous pouvez prendre l'adresse, dynamic_cast et vérifier null. – sharptooth

+0

En outre, jeter et attraper des exceptions est relativement coûteux, et je soupçonne que les concepteurs voulaient trouver un moyen de minimiser ce coût. –

8

Oui, 5.2.7/9

La valeur d'un type moulé a échoué à pointeur est la valeur de pointeur null du type de résultat souhaité. Une conversion manquante au type de référence renvoie bad_cast (18.5.2).

18

Voir la norme C++, section 5.2.7/9:

9 La valeur d'une distribution pas type de pointeur est la valeur de pointeur null du type de résultat souhaité. Un échec de conversion au type de référence renvoie bad_cast (18.5.2).

Quant à savoir pourquoi - ce sont les mots de Stroustrup du livre D & E, section 14.2.2:

J'utilise un casting de référence quand je veux une hypothèse sur un type de référence vérifié et Considérer comme un échec pour mon hypothèse à tort. Si à la place je veux choisir parmi les alternatives plausibles , j'utilise un cast de pointeur et tester le résultat.

+1

J'apprécie le travail supplémentaire dans cette réponse pour associer à la fois l'interprétation standard et celle de Stroustrup. –