IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
logo

FAQ C++Consultez toutes les FAQ

Nombre d'auteurs : 34, nombre de questions : 368, derni�re mise � jour : 14 novembre 2021  Ajouter une question

 

Cette FAQ a �t� r�alis�e � partir des questions fr�quemment pos�es sur les forums de http://www.developpez.com et de l'exp�rience personnelle des auteurs.

Je tiens � souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes ; les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne pr�tend pas non plus �tre compl�te. Si vous trouvez une erreur ou si vous souhaitez devenir r�dacteur, lisez ceci.

Sur ce, nous vous souhaitons une bonne lecture.

SommaireUtilisation des exceptions (13)
pr�c�dent sommaire suivant
 

Les exceptions sont un nouveau moyen de g�rer les erreurs dans les programmes. La grande diff�rence vis � vis du classique code d'erreur renvoy� par une fonction est qu'une exception se propage depuis l'appel� vers l'appelant jusqu'� ce qu'elle rencontre un bloc de code qui s'occupe de la traiter. Au contraire d'un code d'erreur qui peut �tre ignor� (ce qui est malheureusement souvent le cas) une exception doit �tre trait�e. Si elle ne l'est pas dans la fonction qui en est � l'origine, elle doit l'�tre dans l'une des fonctions appelantes. Le compilateur s'occupe tout seul de faire en sorte que l'exception remonte le long de la pile des appels jusqu'� l'endroit o� un bloc a �t� pr�vu pour la traiter. Cela permet donc de facilement faire � remonter � les erreurs des fonctions appel�es vers les fonctions appelantes. L'apparition d'une exception interrompt l'ex�cution normale du programme et provoque sa reprise dans le gestionnaire d'exception le plus proche (qui peut se trouver beaucoup plus en amont dans une fonction appelante).
Le programmeur n'a donc plus � se soucier de tester la r�ussite ou non des fonctions qu'il appelle au moyen d'un grand nombre de tests comme dans l'exemple suivant :

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// ces fonctions renvoient false en cas d'erreur 
bool F1(); 
bool F2(); 
bool F3(); 
bool F4(); 
  
bool Test1() 
{ 
    // appeler F1 et F2 
    if ( !F1() ) 
    { 
        return false; 
    } 
    if ( !F2() ) 
    { 
        return false; 
    } 
    return true; 
} 
  
bool Test2() 
{ 
    // appeler Test1 et F3 
    if ( !Test1() ) 
    { 
        return false; 
    } 
    if ( !F3() ) 
    { 
        return false; 
    } 
    return true; 
} 
  
bool Test3() 
{ 
    // appeler Test2 et F4 
    if ( !Test2() ) 
    { 
        return false; 
    } 
    if ( !F4() ) 
    { 
        return false; 
    } 
    return true; 
} 
  
int main() 
{ 
    if ( !Test3() ) 
    { 
        std::cerr << "Une erreur est survenue, mais je ne sais pas o� !"; 
    } 
}
Les exceptions permettent de grandement simplifier le code pr�c�dent tout en am�liorant la qualit� du renseignement sur l'origine de l'erreur :

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// ces fonctions l�vent des exceptions en cas d'erreur 
void F1(); 
void F2(); 
void F3(); 
void F4(); 
  
void Test1() 
{ 
    F1(); 
    F2(); 
} 
  
void Test2() 
{ 
    Test1(); 
    F3(); 
} 
  
void Test3() 
{ 
    Test2(); 
    F4(); 
} 
  
int main() 
{ 
    try 
    { 
        Test3(); 
    } 
    catch ( const std::bad_alloc & ) 
    { 
         std::cerr << "Erreur : m�moire insuffisante.\n"; 
    } 
    catch ( const std::out_of_range & ) 
    { 
         std::cerr << "Erreur : d�bordement de m�moire.\n"; 
    } 
}

Mis � jour le 22 novembre 2004 Aurelien.Regat-Barrel

Les exceptions sont d�clench�es gr�ce � l'utilisation du mot-cl� throw :

Code c++ : S�lectionner tout
1
2
// l�ve une exception de type e 
throw e;
Les exceptions peuvent �tre de n'importe quel type (type de base du langage ou classe quelconque). Mais il est conseill� d'utiliser une classe d�rivant de la classe standard std::exception d�finie dans le fichier d'en-t�te standard <exception>. Cette classe dispose d'une fonction membre what() qui renvoie une description de l'exception.

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
try 
{ 
    // instructions pouvant d�clencher des exceptions 
    // d�rivant de std::exception 
} 
catch ( const std::exception & e ) 
{ 
    std::cerr << e.what(); 
}
Les exceptions doivent �tre de pr�f�rence d�clench�es par valeur, et attrap�e par r�f�rence. D�clencher une exception par pointeur pose en effet un probl�me :

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
try 
{ 
    // d�clencher une exception par pointeur 
    throw new int( 10 ); 
} 
catch ( const int * e ) 
{ 
    std::cerr << "Erreur num�ro " << *e; 
}
Le code pr�c�dent fonctionne mais une question subsiste : comment est lib�r� le pointeur allou� dans le bloc try ? La r�ponse est qu'il ne l'est pas, et il se produit donc une fuite de m�moire. Le probl�me de d�clencher une exception par pointeur est donc de savoir � qui incombe la responsabilit� de lib�rer ce dernier. Voil� pourquoi on pr�f�re lever des exceptions par valeur, et les attraper par r�f�rence (de pr�f�rence constante) afin de permettre le polymorphisme et d'am�liorer les performances en �vitant une recopie de l'objet.

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream> 
#include <stdexcept> 
  
int main() 
{ 
    try 
    { 
        // std::logic_error est une classe standard 
        // qui d�rive de std::exception 
        throw std::logic_error( "Exemple d'exception" ); 
    } 
    catch ( const std::exception & e ) 
    { 
        // affiche "Exemple d'exception" 
        std::cerr << e.what(); 
    } 
}
Un cas particulier est celui des cha�nes de caract�res litt�rales :

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
try 
{ 
    throw "Message d'erreur"; 
} 
catch ( const char * Msg ) 
{ 
    std::cerr << Msg; 
}
Dans l'exemple pr�c�dent, bien qu'on utilise un pointeur, il n'y a pas de fuite de m�moire tout simplement parce qu'il n'y a pas d'allocation dynamique. Ce serait m�me une grosse erreur de lib�rer ce pointeur avec delete [] car ce dernier pointe vers une zone de m�moire sp�ciale (g�n�ralement en lecture seule) qui contient l'ensemble de cha�nes de caract�res litt�rales utilis�es dans le programme. Donc, � priori, utiliser des cha�nes litt�rales est une bonne id�e, mais cela est n�anmoins d�conseill� car leur utilit� est vite limit�e du fait de l'impossibilit� de formater les cha�nes pour donner la valeur d'une variable par exemple. Il y a fort � craindre que t�t ou tard un programmeur voudra effectuer cette op�ration et provoquera alors inconsciemment une fuite de m�moire (car dans le bloc catch il n'y a aucun moyen de distinguer une cha�ne litt�rale d'une cha�ne allou�e avec new []).
Si vous persistez � vouloir utiliser de simple cha�nes de caract�res au lieu d'une classe d�rivant de std::exception, utilisez au moins le type cha�ne de caract�res du C++ : std::string.

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
try 
{ 
    throw std::string( "Message d'erreur" ); 
} 
catch ( const std::string & Msg ) 
{ 
    std::cerr << Msg; 
}

Mis � jour le 22 novembre 2004 Aurelien.Regat-Barrel

Le code susceptible de d�clencher des exceptions doit �tre plac� dans un bloc try...catch (essaye...attrape) de cette mani�re :

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
int * ptr; 
try 
{ 
    // tenter d'allouer 100 entiers 
    ptr = new int [ 100 ]; 
} 
catch ( const std::bad_alloc & ) 
{ 
    // �chec de l'allocation 
}
On peut mettre autant de blocs catch qu'il y a d'exceptions � rattraper.

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
try 
{ 
    // cr�er un tableau de taille 10 
    std::vector<int> tableau( 10 ); 
    // acc�der au 11� �l�ment 
    tableau.at( 10 ); 
} 
catch ( const std::exception & Exp ) 
{ 
    std::cerr << "Erreur : " << Exp.what() << ".\n"; 
} 
catch ( const std::bad_alloc & ) 
{ 
    std::cerr << "Erreur : m�moire insuffisante.\n"; 
} 
catch ( const std::out_of_range & ) 
{ 
    std::cerr << "Erreur : d�bordement de m�moire.\n"; 
}
Les exceptions lev�es dans le bloc try vont �tre filtr�es par les diff�rents blocs catch suivant leur ordre d'apparition. Ce filtrage est effectu� en fonction du type de l'exception, et est naturellement sensible au polymorphisme. C'est-�-dire que le premier bloc catch rencontr� capable de traiter l'exception lev�e est celui qui est utilis�. Les autres sont ignor�s, m�me si certains seraient mieux adapt�s. En l'occurrence, dans l'exemple pr�c�dent, l'exception out_of_range est lev�e et ce serait tout naturellement le dernier bloc catch qui devrait la traiter. Mais std::out_of_range d�rive de std::exception qui est la classe de base pour les exceptions standards, et donc c'est le premier bloc catch qui est appel�.
Il existe aussi un moyen d'attraper toutes les exceptions, en utilisant une ellipse (...) comme type de l'exception. Mais alors il n'y a aucun moyen de conna�tre l'origine et le type de l'exception (sauf � la relancer et la traiter dans un nouveau bloc try...catch). L'utilisation de cette forme g�n�rique doit �tre restreinte car elle ne permet de savoir si l'exception captur�e peut �tre trait�e et ignor�e ou si elle n�cessite de terminer le programme (corruption de la m�moire, etc.). On l'utilise en g�n�ral comme dernier recours.

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
try 
{ 
    // cr�er un tableau de taille 10 
    std::vector<int> tableau( 10 ); 
    // acc�der au 11� �l�ment 
    tableau.at( 10 ); 
} 
catch ( const std::bad_alloc & ) 
{ 
    std::cerr << "Erreur : m�moire insuffisante.\n"; 
} 
catch ( const std::out_of_range & ) 
{ 
    std::cerr << "Erreur : d�bordement de m�moire.\n"; 
} 
catch ( const std::exception & Exp ) 
{ 
    std::cerr << "Erreur : " << Exp.xhat() << ".\n"; 
} 
catch ( ... ) // traite toutes les autres exceptions 
{ 
    std::cerr << "Erreur inconnue.\n"; 
}
Il est donc important de faire appara�tre les blocs catch des classes d�riv�es en premier.
Notez que les exceptions sont r�cup�r�es par r�f�rence, comme cela est expliqu� dans la question Pourquoi faut-il capturer les exceptions par r�f�rence ?. Ces r�f�rences ne sont cependant pas des r�f�rences sur l'objet initial qui est � l'origine de l'exception, mais sur une copie de celui-ci, car l'objet initial risque d'�tre d�truit si l'on quitte la fonction qui a lev� l'exception.

Mis � jour le 17 mars 2008 Aurelien.Regat-Barrel

Comme discut� dans la question Comment lever une exception ?, il est fortement recommand� de lever des exceptions par valeur. En revanche, il vaut mieux les capturer par r�f�rence et non pas par valeur. Tout d'abord cela permet d'�viter une recopie, mais aussi et surtout cela permet de conserver le polymorphisme. L'exemple suivant illustre les probl�mes pos�s par un traitement des exceptions par valeur�:

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream> 
#include <stdexcept> 
  
int main() 
{ 
    using namespace std; 
  
    try 
    { 
        // std::logic_error h�rite de std::exception 
        throw logic_error( "exception de test" ); 
    } 
    catch ( exception e ) // traitement par valeur 
    { 
        cerr << e.what(); 
    } 
}
Cet exemple affiche le message Unknown exception. Si l'on remplace le traitement par valeur par un traitement par r�f�rence�:

Code c++ : S�lectionner tout
catch ( const exception & e ) // traitement par r�f�rence
Alors on obtient le message attendu exception de test. Ceci est d� au fait que le polymorphisme n�cessite d'utiliser un pointeur ou une r�f�rence, autrement dans notre cas l'objet de type std::logic_error est � tronqu� � en un objet de type std::exception. La fonction membre what appel�e n'est donc pas celle de std::logic_error mais celle de std::exception, qui n'est pas d'une grande utilit�.
Donc � moins de rechercher volontairement ce comportement, il est recommand� de traiter les exceptions par r�f�rence, de pr�f�rence constantes afin de permettre au compilateur d'effectuer des optimisations.

Mis � jour le 22 novembre 2004 Aurelien.Regat-Barrel

Malheureusement, non, ce m�canisme n'est pas possible. Un catch ne pouvant capturer qu'un seul type d'exceptions, il faut d�finir autant de blocs try/catch qu'il y a d'exceptions possibles.

L'utilisation de

Code c++ : S�lectionner tout
1
2
3
4
5
try { 
    // ... 
} catch(...) { 
    // ... 
}
permet de capturer toutes les exceptions pouvant survenir, mais il est, dans ce cas, impossible de faire la distinction.

Mis � jour le 9 octobre 2003 LFE

Le mot-cl� throw permet de lever une nouvelle exception, mais aussi de relancer celle qui est en cours de traitement.

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream> 
#include <stdexcept> 
  
void Test() 
{ 
    try 
    { 
        throw std::logic_error( "Exception de test" ); 
    } 
    catch ( const std::logic_error & e ) 
    { 
        std::cerr << "L'exception '" << e.what() 
                  << "' a �t� lev�e et va �tre relanc�e.\n"; 
        throw; // relancer l'exception courante 
    } 
} 
  
int main() 
{ 
    try 
    { 
        Test(); 
    } 
    catch ( const std::logic_error & e ) 
    { 
        std::cerr << "Erreur : " << e.what() << ".\n"; 
    } 
}

Mis � jour le 22 novembre 2004 Aurelien.Regat-Barrel

Lorsqu'une exception est d�clench�e, le compilateur recherche un bloc catch capable de la traiter. S'il n'en trouve pas, il remonte la pile d'ex�cution (d�roulage de la pile) afin d'en trouver un plus en amont dans la hi�rarchie des appels. D�piler un appel revient � quitter une fonction. A cette occasion ses objets locaux sont d�truits et les destructeurs appel�s, ce qui permet de quitter proprement la fonction en lib�rant toutes les ressources acquises si les destructeurs on �t� bien �crits. L'objet qui a servi � lever l'exception est lui m�me d�truit car il est local � la fonction. C'est pourquoi l'objet qui est transmis aux blocs catch est toujours une copie de l'objet initial qui a d�clench� l'exception.
Si la pile des appels est vid�e (donc que l'on est arriv� � main) et qu'aucun bloc catch satisfaisant n'a �t� trouv�, la fonction standard terminate est appel�e ce qui provoque par d�faut un arr�t pur et simple du programme. Ce comportement peut �tre modifi� au moyen de la fonction set_terminate d�finie dans l'en-t�te standard <exception>. Cette fonction installe un nouveau gestionnaire et renvoie l'adresse du pr�c�dent. Elle s'utilise de cette mani�re :

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream> 
#include <exception> 
  
// ancien gestionnaire 
void (*old_handler)(); 
  
// gestionnaire personnalis� 
void my_handler() 
{ 
    std::cerr << "Exception inattendue.\n"; 
    // appel du gestionnaire par d�faut 
    (old_handler)(); 
} 
  
int main() 
{ 
    // installer notre gestionnaire personnalis� 
    old_handler = set_terminate( my_handler ); 
    // lever une exception que l'on ne traite pas 
    throw "test"; 
}
Le code pr�c�dent provoque le r�sultat suivant avec le compilateur Visual C++ 7.1 :

Exception inattendue.
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

Mis � jour le 22 novembre 2004 Aurelien.Regat-Barrel

N'importe quel type de base ou classe C++ peut �tre utilis� comme type d'exception. Mais il est pr�f�rable de cr�er son type qui h�rite de la classe de base standard pour les exceptions : std::exception d�finie dans l'en-t�te <exception>. Cette classe poss�de une fonction membre virtuelle what() qu'il convient de red�finir :

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream> 
#include <sstream> 
#include <exception> 
  
class my_exception : public std::exception 
{ 
public: 
    my_exception( const char * Msg, int Line ) 
    { 
        std::ostringstream oss; 
        oss << "Erreur ligne " << Line << " : " 
            << Msg; 
        this->msg = oss.str(); 
    } 
  
    virtual ~my_exception() throw() 
    { 
  
    } 
  
    virtual const char * what() const throw() 
    { 
        return this->msg.c_str(); 
    } 
  
private: 
    std::string msg; 
}; 
  
int main() 
{ 
    try 
    { 
        throw my_exception( "exception test", __LINE__ ); 
    } 
    catch ( const std::exception & e ) 
    { 
        std::cerr << e.what() << "\n"; 
    } 
}
Cet exemple produit le r�sultat suivant :

Erreur ligne 29 : exception test

Mis � jour le 17 mars 2008 Aurelien.Regat-Barrel

Tout � fait. C'est m�me une des seules mani�res d'indiquer que l'initialisation de l'objet a �chou�. Il faut cependant �tre prudent car une exception lev�e dans un constructeur peut �tre � l'origine de fuites de m�moires ou d'autres probl�mes de non lib�ration de ressources. C'est le cas dans l'exemple suivant :

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Test 
{ 
public: 
    // exception bad_alloc en cas de m�moire insuffisante 
    Test( int A, int B ) : 
        tableau1( 0 ), 
        tableau2( 0 ) 
    { 
        // ici tableau1 et tableau2 valent NULL, donc en cas d'�chec d'allocation 
        // on peut appeler delete [] sans probl�me dans le destructeur 
        this->tableau1 = new int[ A ]; 
        this->tableau2 = new int[ B ]; 
    } 
    ~Test() 
    { 
        delete [] this->tableau2; 
        delete [] this->tableau1; 
    } 
  
private: 
    int * tableau1; 
    int * tableau2; 
};
L'id�e du code ci-dessus est d'initialiser les pointeurs tableau1 et tableau2 � z�ro ainsi si l'une des allocations �choue on peut tout de m�me appeler en toute s�r�nit� delete [] dans le destructeur et ainsi �viter les fuites de m�moire (souvenez vous, appeler delete sur un pointeur nul ne fait rien, voir Que se passe-t-il si je fais un delete sur un pointeur qui vaut NULL ?).
Le probl�me est que si une exception est lev�e lors de la construction d'un objet, c'est donc que celle-ci a �chou�, et donc que l'objet n'est pas cr��. Comme il n'est pas cr��, il n'a pas � �tre d�truit, et donc son destructeur ne sera pas appel�. Autrement dit, si une exception est lev�e dans le constructeur d'un objet, son destructeur ne sera pas appel�.
Il faut donc toujours s'assurer que le code contenu dans le constructeur est exception safe, c'est-�-dire qu'il r�siste aux exceptions en ne provoquant pas de pertes de ressources. Dans notre exemple pr�c�dent cela signifie qu'il faut g�rer l'exception bad_alloc de cette mani�re :

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Test 
{ 
public: 
    // exception bad_alloc en cas de m�moire insuffisante 
    Test( int A, int B ) : 
        tableau1( 0 ) 
    { 
        // ici tableau1 vaut NULL, donc en cas d'�chec d'allocation 
        // on peut appeler delete [] sans probl�me 
        try 
        { 
            this->tableau1 = new int[ A ]; 
            this->tableau2 = new int[ B ]; 
        } 
        catch ( const std::bad_alloc & ) 
        { 
            // tableau2 n'a pas �t� allou� quoi qu'il arrive 
            // lib�rer tableau1 s'il a pu �tre allou� 
            delete [] this->tableau1; 
            // relancer l'exception 
            throw; 
        } 
    } 
    ~Test() 
    { 
        delete [] this->tableau2; 
        delete [] this->tableau1; 
    } 
  
private: 
    int * tableau1; 
    int * tableau2; 
};
Le nouveau code produit toujours une exception bad_alloc en cas d'�chec d'allocation, mais cette fois-ci il n'y a plus de fuite de m�moire. Ce qui a pu �tre allou� est lib�r�, et l'exception bad_alloc captur�e est relanc�e via l'instruction throw (� ce sujet lire Comment relancer une exception que l'on a captur� ?).
Il est � noter que si en cas d'exception dans le constructeur le destructeur n'est pas appel�, tous les membres construits jusqu'au point de l'exception sont quant � eux bien d�truits.

Mis � jour le 22 novembre 2004 Aurelien.Regat-Barrel Luc Hermitte

Il est possible de lever une exception dans un destructeur, mais c'est extr�mement d�conseill� et consid�r� comme une tr�s mauvaise pratique. La raison en est simple : si la destruction d'un objet �choue, que faut-il faire ? Mais aussi un autre probl�me plus grave peut appara�tre. Lorsqu'une exception est lev�e, la pile des appels est remont�e (on parle de stack unwinding ou d�roulage de la pile) et � cette occasion les objets locaux de la fonction que l'on s'appr�te � quitter sont d�truits. Donc leur destructeur respectif est appel�. Si l'un d'entre eux vient � lever une exception, la situation devient alors tr�s complexe : laquelle des deux exceptions faut-il g�rer ? N'oubliez pas qu'� ce moment nous ne sommes toujours pas dans un bloc catch, mais en train de nous y rendre en quittant les fonctions appel�es qui nous en s�pare.
Or, en quittant l'une d'entre elles, on d�truit un objet qui lance une nouvelle exception, et nous nous retrouvons alors avec deux exceptions � traiter en m�me temps. La situation �tant insoluble, la norme d�finit que la fonction standard terminate est appel�e dans un tel cas, ce qui provoque la fin brutale du programme.
Pour cette tr�s bonne raison, il est important que les destructeurs ne l�vent jamais d'exceptions. On peut s'en assurer en appelant uniquement des fonctions n'�chouant jamais (voir Comment indiquer qu'une fonction ne l�ve jamais d'exception�?).

Mis � jour le 22 novembre 2004 Aurelien.Regat-Barrel

Il est possible d'utiliser noexcept pour le faire, et il est particuli�rement recommand� de le faire pour certaines op�rations comme les constructeurs par d�placement [Ajouter un lien vers une nouvelle entr�e de la faq � cr�er sur le sujet].
Cette d�claration peut s'utiliser de mani�re simple ou conditionnelle :

Code : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
void f1() noexcept // Cette fonction ne lance pas d'exceptions 
{ 
  //... 
}  
 
void f2() noexcept(true) // Cette fonction non plus 
{ 
  //... 
}  
 
void f3() noexcept(noexcept(g) && noexcept(h)) // Cette fonction ne lance pas d'exceptions si g et h sont aussi d�clar�s noexcept 
{ 
  //... 
}
Si une fonction ayant promis d'�tre noexcept laisse quand m�me �chapper une exception, la fonction std::terminate est appel�e (ce qui interrompt le remont�e de la pile d'appels).
Certaines fonctions sont par d�faut noexcept : Les destructeurs et les operator delete.

� noter : Les sp�cifications d�exceptions sont d�pr�ci�es, et leur usage n'est pas recommand�.

Mis � jour le 2 juillet 2016 JolyLoic

Il n'y a pas de moyen direct. Utiliser une sp�cification d'exception vide permet de simuler �a, et certains compilateurs consid�rent ce cas un peu diff�remment d'une sp�cification d'exception non vide:

Code : S�lectionner tout
1
2
3
void Test() throw () 
{ 
}
Si une exception s'�chappe quand m�me de la fonction, la fonction std::unexpected est appel�e.

Mis � jour le 22 novembre 2004 Aurelien.Regat-Barrel JolyLoic

Dans certains langages (tels que Java ou C#), il est possible de cr�er un bloc finally � la suite d'un bloc try...catch afin de s'assurer qu'une op�ration (de lib�ration de ressource par exemple) soit bien effectu�e. Par exemple, en C++ on ne peut pas �crire ceci :

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
char * buffer = new char[ 100 ]; 
try 
{ 
    // op�ration susceptible de lever une exception 
} 
finally 
{ 
    // s'assurer que la m�moire est lib�r�e 
    delete [] buffer; 
}
l'�quivalent de l'�criture ci-dessus serait :

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
char * buffer = new char[ 100 ]; 
try 
{ 
    // op�ration susceptible de lever une exception 
} 
catch ( ... ) 
{ 
    // �viter les fuites de m�moire 
    delete [] buffer; 
    // relancer l'exception 
    throw; 
} 
// tout s'est bien pass�, lib�rer la m�moire 
delete [] buffer;
Mais il ne s'agit l� que d'une traduction en C++ d'une approche issue d'un autre langage. Or, quand on programme dans un langage, il convient de le faire selon les concepts propres � ce langage, et non avec ceux d'un autre. L'approche C++ � ce probl�me consiste � encapsuler cette gestion au sein d'un objet qui s'assurera dans son destructeur de la bonne lib�ration de la ressource qu'il g�re. Ainsi, on est assur� de ne pas avoir de fuite m�me en cas d'exception, tout en ayant une �criture plus l�g�re car le bloc try...catch devient inutile dans ce cas.
Ce principe s'appelle le RAII, et est d�velopp� dans la question Comment g�rer proprement des allocations / d�sallocations de ressources ? Le RAII !.

Mis � jour le 17 octobre 2005 Aurelien.Regat-Barrel

Proposer une nouvelle r�ponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plut�t sur le forum de la rubrique pour �a


R�ponse � la question

Liens sous la question
pr�c�dent sommaire suivant
 

Les sources pr�sent�es sur cette page sont libres de droits et vous pouvez les utiliser � votre convenance. Par contre, la page de pr�sentation constitue une �uvre intellectuelle prot�g�e par les droits d'auteur. Copyright � 2025 Developpez Developpez LLC. Tous droits r�serv�s Developpez LLC. Aucune reproduction, m�me partielle, ne peut �tre faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'� trois ans de prison et jusqu'� 300 000 � de dommages et int�r�ts.