2010-10-18 4 views
3

1) Pour plus de commodité, j'ai tout mon programme dans un bloc try. De cette façon, je peux lancer une exception à tout moment dans mon code et je sais qu'il sera traité de la même manière. Au fur et à mesure que le programme s'élargira, cette technique causera-t-elle un coup dans la performance?C++ Exception Handling Questions

2) Si les objets sont désaffectés hors champ, pourquoi lancer un objet temporaire est-il valide? .: par exemple

class Error : public std::exception 
{ 
    private: 
    char *m; 
    private: 
    Error(char *l) : m(l) {} 
    virtual char *what() 
    { 
     return m; 
    } 
}; 

int main() 
{ 
    try 
    { 
    throw Error("test"); 
    } 
    catch(std::exception &e) 
    { 
    puts(e.what()); 
    return -1; 
    } 
    return 0; 
}

Dans l'instruction throw, pourquoi ne pas l'objet temporaire devient invalide car il a été déclaré que dans le cadre essayer?

3) Avec les systèmes d'exploitation Windows d'une langue autre que l'anglais, le membre what() de la classe d'exception STL renvoie-t-il toujours une chaîne char*? Ou pourrait-il retourner une chaîne wchar_t*?

+3

Vous ne devriez pas avoir votre programme entier dans un bloc try. Si vous obtenez une erreur, tout votre programme se termine plutôt que de vous permettre de le gérer avec élégance et de continuer. Ce genre défait le but des exceptions. – JoshD

+7

Je ne suis pas d'accord, si vous consignez des informations significatives de l'exception à ce niveau, alors il est parfaitement valide. Cela vous donne une meilleure information que si std :: terminate était appelé, ce qui arrive si l'exception n'est pas interceptée. – radman

+1

@JoshD dans certaines zones de mon code, je pourrais avoir plus de blocs try-catch, avec lesquels je pourrais gérer avec élégance les exceptions. Le premier bloc try-catch serait de gérer les erreurs fatales où le programme ne pourrait pas continuer plus loin. – kaykun

Répondre

4

1) Avoir tout le programme dans un bloc d'essai ne contractera aucune perte de performance, à l'exception de celle encourue en ayant des exceptions activées à tous

2) Il est OK parce que vous jetez en valeur. Lancer par valeur signifie que tout ce que vous lancez est copié lorsqu'il est lancé. Donc jeter n'importe quel temporaire est parfaitement valide car une copie est faite.

3) La classe std :: exception, pour autant que je puisse déterminer, peut seulement lancer char*. Cependant, vous pouvez toujours le sous-classer et implémenter le support pour wchar si vous le souhaitez.

Il est à noter que vous ne devriez pas juste essayer de contourner main() si c'est ce que vous aviez l'intention.

9

Techniquement vous ne lancez pas l'objet réel, vous en jetez une copie. C'est pourquoi vous pouvez vous en sortir en lançant un temporaire. Attraper une référence obtient également une référence à la copie.

Cela peut vous mordre si vous relancez une exception à l'intérieur d'un bloc catch, vous pouvez être victime du problème de tranchage. Voilà pourquoi vous ne faites pas:

catch (std::exception & e) 
{ 
    throw e; // bad, always throws std::exception rather than what was caught 
} 

Mais plutôt

catch (std::exception & e) 
{ 
    throw; // good, rethrows the exact copy that you caught without making another copy 
} 

post-scriptum Il n'y a pas de règle disant que vous ne pouvez pas retourner une chaîne UTF-8 de what. Ce serait à vous de le convertir en UTF-16 pour Windows I/O. Les classes d'exceptions standard n'ont jamais été explicitement conçues ou étendues pour Unicode, et aucune extension non standard n'est ajoutée pour Windows uniquement.

+0

en fait ... au moins sur MSVC (2005), republier avec par ex. 'throw e;' fonctionne aussi longtemps que vous avez attrapé par référence ... – smerlin

+0

@smerlin: pour le premier exemple de Mark, "working" signifie découper l'exception. Si ce n'est pas le cas, c'est une implémentation C++ non conforme. –

+0

@Steve: fait un autre test, et les clauses catch entourant le rethrow, seulement attrapé l'exception comme une exception std ::, mais le débogueur présentait toujours toutes les informations de l'exception originale. Il semble donc que le compilateur soit conforme aux standards, au moins en mode release, il découpe l'exception complètement. – smerlin