2009-10-19 6 views
3

Je sais que c'est un programme C++ valide. Quel est le point du lancer dans la déclaration de fonction? AFAIK il ne fait rien et n'est pas utilisé pour n'importe quoi.Quel est le point de `void func() throw (type)`?

#include <exception> 
void func() throw(std::exception) { } 
int main() { return 0; } 
+0

Une des choses en C++ que j'ai appris, mais jamais utilisé, ni je :) – AraK

+3

« ne prennent pas la peine avec les spécifications d'exception. Même les experts ne prennent pas la peine. Ils ne font pas ce que la plupart des gens pensent, et vous ne voulez presque jamais ce qu'ils font réellement. Andrei Alexandrescu & Herb Sutter – KeatsPeeks

+0

Autant que je respecte Sutter et Alexandrescu. Mais c'est un mauvais conseil. Juste parce qu'ils sont mauvais ne signifie pas que vous ne devriez pas les apprendre. Cela vous aidera à expliquer aux autres pourquoi ils sont mauvais et à vous faire comprendre pourquoi vous devriez les éviter. Non seulement appliquer une règle dogmatique est une bonne chose. –

Répondre

12

C'est une spécification d'exception, et c'est presque certainement un bad idea.

Il affirme que func peut jeter un std::exception, et toute autre exception que func émet entraînera un appel à unexpected().

0

Ceci est une spécification d'exception. Il dit que la seule exception que func() peut lancer est std :: exception (ou une dérivée de celle-ci). Tenter de lancer une autre exception donnera std :: unexpected à la place.

0

Spécification d'exception. Le (s) type (s) suivant le mot-clé throw spécifie exactement toutes les exceptions, le cas échéant, que la fonction peut lancer. Voir 15.4 du projet.

Remarque: Une fonction sans spécification d'exception autorise toutes les exceptions. Une fonction avec une spécification d'exception vide, throw(), n'autorise aucune exception.

2

Ceci est une spécification d'exception C++. Il déclare que la fonction particulière peut potentiellement lancer un type std::exception.

En général, les spécifications d'exception en C++ sont considérées comme une caractéristique à éviter. C'est une caractéristique étrange en ce que son comportement est déclaré lors de la compilation mais seulement vérifié lors de l'exécution (très différent de la version de Java par exemple).

Voici un bon article qui décompose la fonction

+0

La différence avec Java est ce qui m'a dérouté quand j'ai commencé à apprendre le C++. Je les ai utilisés partout parce qu'ils se sentaient familiers, puis plus tard, ils les ont tous supprimés après avoir lu GOTW. –

17

Il précise que toute std::exception peut être jeté de func(), et rien d'autre. Si quelque chose d'autre est lancé, il appellera une fonction unexpected() qui appelle par défaut terminate(). Cela signifie que le fait de lancer quelque chose d'autre terminera presque certainement le programme, de la même manière qu'une exception non interceptée, mais l'implémentation devra l'appliquer. Cela revient normalement à mettre un bloc try{...}catch(){...} autour de func(), ce qui peut nuire aux performances.

Habituellement, les spécifications d'exception ne valent pas la peine, selon la colonne the Guru of the Week à ce sujet. Le Boost guidelines dit qu'il pourrait y avoir un léger avantage avec un vide throws() pour une fonction non-inline, et il y a des inconvénients.

+0

Meilleure réponse. Les apprenants doivent savoir qu'ils ne devraient pas les déranger. – KeatsPeeks

+0

J'aime vraiment cette réponse et j'ai eu du mal à choisir. Dominic gagne parce que j'aime habituellement les réponses qui sont 1-2 phrase avec des liens. –

0

Fondamentalement ceci:

void func() throw(std::exception,B) { /* Do Stuff */} 

Est-ce que la sténographie vient ceci:

void func() 
{ 
    try 
    { 
     /* Do Stuff */ 
    } 
    catch(std::exception const& e) 
    { 
     throw; 
    } 
    catch(B const& e) 
    { 
     throw; 
    } 
    catch(...) 
    { 
     unexpected(); // This calls terminate 
         // i.e. It never returns. 
    } 
} 

appel résiliez() est rarement ce que vous voulez, que la pile ne dévidé et donc tous vos efforts en RAII est gâché.La seule exception à la règle est la déclaration d'une liste de lancements vides et ceci est principalement à des fins de documentation pour montrer que vous soutenez la garantie d'exception sans lancer (vous devriez toujours attraper manuellement toutes les exceptions dans cette situation).

Certains endroits importants (imho) qui devraient être non-throw sont des destructeurs et des méthodes swap(). Les destructeurs sont rarement marqués explicitement no-throw mais swap() sont souvent marqués no-throw.

void myNoThrowFunc() throws() // No-Throw (Mainlly for doc purposes). 
{ 
    try 
    { 
     /* Do Stuff */ 
    } 
    catch(...) // Make sure it does not throw. 
    { 
     /* Log and/or do cleanup */ 
    } 
} 
Questions connexes