#1 Le 05/11/2008, à 14:10
- rniamo
C++ et exceptions [Résolu]
bonjour,
j'ai 2 questions concernant les exceptions :
1) est ce que l'on doit mettre un mot clef du type "throws" dans la déclaration des fonctions (un peu comme en java) :
ex : void mafonction() throws Exception;
2) je vois souvent sur le net :
try {
mafonction()
}
catch(Exception& e) {
blablablabis(e);
}
avec mafonction() qui peut faire un
throw Exception(param);
Hors là on récupère une référence qui n'éxiste plus donc est ce correcte ? pour quoi pas du passage par valeur / adresse ?
Dernière modification par rniamo (Le 05/11/2008, à 23:02)
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#2 Le 05/11/2008, à 15:06
- tiky
Re : C++ et exceptions [Résolu]
Salut,
1. Le mot-clé throw lors de la déclaration d'une fonction ou d'une méthode est facultatif. Le mot-clé permet de définir la liste d'exceptions autorisées à être levées dans cette fonction.
2. Les exceptions sont passés soit par valeur, soit par référence, jamais par pointeur.
Pour récupérer l'exception avec catch, tu peux soit demander une référence dessus, soit une copie. Si tu demandes une référence, toutes les modifications faites dessus seront disponibles dans les catch de niveau supérieur si l'exception est relancée.
Pour avoir plus de détails ( regarde notamment pour le constructeur, c'est très intéressant ):
http://cpp.developpez.com/cours/cpp/?page=page_11#LXI
Conseil d'expert: il vous faut un dentifrice adapté...
Hors ligne
#3 Le 05/11/2008, à 15:11
- rniamo
Re : C++ et exceptions [Résolu]
jamais par adresse ? pourtant ça semble plus logique que par référence. J'ai lu la page de developpez.com et c'est elle qui me fait poser la question.
Je croyais que la variable "exception" était détruite après être remonté si elle est passé par référence => valeur (copie) ou adresse (=> avec un throw new Exception()). Pour moi l'utilisation de référence n'est due qu'à de la chance (gestion mémoire de l'OS) donc j'aimerais éclaircir ce point.
Pour le 1. il faudrait faire : void mafonction() throw Exception; ?
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#4 Le 05/11/2008, à 16:04
- tiky
Re : C++ et exceptions [Résolu]
Lorsque tu lances une exception dans une méthode, l'objet exception lancé est détruit avec l'objet mais le compilateur fait une copie juste avant de détruire l'objet. Ainsi tu peux accéder à une copie de l'objet exception dans les blocs catch ou à une référence sur la copie de l'objet exception. Bien sûr, tu peux envoyer un pointeur par valeur seulement tu n'as aucun moyen propre de libérer la mémoire allouée dynamique ensuite. Le passage par référence est fortement conseillé car il permet tout comme le pointeur le polymorphisme et il n'y a aucune raison de remplacer l'objet exception par un autre comme le permet un pointeur et non une référence.
Dernière modification par tiky (Le 05/11/2008, à 16:05)
Conseil d'expert: il vous faut un dentifrice adapté...
Hors ligne
#5 Le 05/11/2008, à 19:14
- rniamo
Re : C++ et exceptions [Résolu]
oui mais une référence ne nécessite pas de copie (contrairement au passage par valeur), je n'ai pas trouvé le
le compilateur fait une copie juste avant de détruire l'objet
, ou puis-je trouver plus d'informations stp ?
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#6 Le 05/11/2008, à 19:35
- Luc Hermitte
Re : C++ et exceptions [Résolu]
Pinaillons,
1- l'utilisation des spécifications d'exception est une chose déconseillée, voire fortement déconseillée: le truc est qu'elles réalisent une vérification des exceptions qui veulent s'échapper au moment de l'exécution du programme, et non lors de la compilation (c'est impossible en C++).
Et bien sûr, c'est une vérification qui ne peut avoir qu'un seul résultat: arrêter le programme sans aucune chance de l'éviter.
2- On lève les exceptions par valeur (il faut donc qu'elles soient copiables), et on les rattrape par référence (de préférence constante)
NB: on ne lève pas des pointeurs, car cela serait alors inutilement compliqué s'il fallait en plus gérer des désallocation.
CF la FAQ C++ de développez, ou le Coding Standards de Sutter et Alexandrescu.
Hors ligne
#7 Le 05/11/2008, à 19:54
- rniamo
Re : C++ et exceptions [Résolu]
je ne comprends pas l'histoire des références (et c'est contraire à mon cours), le mécanisme de levée d'exception met en place une copie => passage par valeur malgré la référence ?
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#8 Le 05/11/2008, à 19:54
- tiky
Re : C++ et exceptions [Résolu]
Bah c'est ce que je dis...
Conseil d'expert: il vous faut un dentifrice adapté...
Hors ligne
#9 Le 05/11/2008, à 19:58
- rniamo
Re : C++ et exceptions [Résolu]
c'est ce que je ne comprends pas ... c'est contraire à mon cours c'est pour ça que j'insiste.
edit : je ne comprends pas sur developpez la phrase :
Ceci est dû au fait que le polymorphisme nécessite d'utiliser un pointeur ou une référence
Si on a bien mis le mot clef virtual, on peut utiliser le polymorphisme en déclarant un objet, sans référence ou pointeur, non ?
Dernière modification par rniamo (Le 05/11/2008, à 20:02)
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#10 Le 05/11/2008, à 20:02
- tiky
Re : C++ et exceptions [Résolu]
c'est ce que je ne comprends pas ... c'est contraire à mon cours c'est pour ça que j'insiste.
Alors soit ton cours est faux ou mauvais, soit tu te trompes, peux-tu dire ce qui est contraire à ton cours?
En tout cas on ne passe jamais une exception par pointeur, c'est totalement inutile. Je vois pas ce qui te gène dans le passage par référence.
Conseil d'expert: il vous faut un dentifrice adapté...
Hors ligne
#11 Le 05/11/2008, à 20:10
- rniamo
Re : C++ et exceptions [Résolu]
(pour les pointeur ok, c'est juste un façon que je voyais, un peu lourde mais pas totalement fausse)
Dans mon cours : portée = depuis la déclaration jusqu'à la première } (sauf celles de try/catch).
Donc quand on est dans le catch, l'exception n'existe plus (sauf si l'OS n'a pas réutilisé/modifié l'adresse mémoire).
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#12 Le 05/11/2008, à 20:15
- tiky
Re : C++ et exceptions [Résolu]
Tu n'as pas compris le principe du polymorphisme. Tu ne peux utiliser le polymorphisme qu'avec les pointeurs et les références. Exemple:
class A
{
public:
virtual void foo( void ){ ... }
};
class B : public A
{
public:
void foo( void ){ ... }
};
Maintenant on imagine trois fonctions:
void foobar( A * ptr )
{
A->foo();
}
void foobar( A & ref )
{
A.foo();
}
void foobar( A object )
{
A.foo();
}
Avec les deux premières fonctions, tu as totalement le droit de donner un pointeur sur un objet B ou une référence sur un objet B. Grâce au mécanisme du polymorphisme et à la vtable, le compilateur saura qu'il faut appeler la méthode B::foo et non A::foo, par contre si tu veux passer un objet B dans la troisième fonction, l'objet sera coupé, on appelle cela l'object splicing. Le compilateur appellera alors A::foo car les informations de la vtable seront perdues. Et d'ailleurs tout ce qui n'est pas déclaré dans A ( méthodes et variables ) seront également perdus.
Dernière modification par tiky (Le 05/11/2008, à 20:20)
Conseil d'expert: il vous faut un dentifrice adapté...
Hors ligne
#13 Le 05/11/2008, à 20:22
- rniamo
Re : C++ et exceptions [Résolu]
3) ok, je vois (au passage c'est quoi la vtable ?)
par contre ça m'explique la phrase de developpez.com (merci).
2) Donc en fait mon cours qui ne dis pas qu'une copie des exceptions est remonté est faux ?
1) void f() throw Exception(); est correct ?
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#14 Le 05/11/2008, à 20:28
- tiky
Re : C++ et exceptions [Résolu]
(pour les pointeur ok, c'est juste un façon que je voyais, un peu lourde mais pas totalement fausse)
Dans mon cours : portée = depuis la déclaration jusqu'à la première } (sauf celles de try/catch).
Donc quand on est dans le catch, l'exception n'existe plus (sauf si l'OS n'a pas réutilisé/modifié l'adresse mémoire).
Lorsque tu lèves une exception l'objet qui a levé l'exception est détruit et même si c'était pas le cas, l'objet exception serait détruit quand même lorsque la fonction serait dépilées car il n'existe que dans sa portée. Quand tu es dans le catch l'objet exception original n'existe plus mais une copie exacte de celui-ci a été effectué par le compilateur donc tu y accèdes de façon transparente.
Dernière modification par tiky (Le 05/11/2008, à 20:29)
Conseil d'expert: il vous faut un dentifrice adapté...
Hors ligne
#15 Le 05/11/2008, à 20:29
- rniamo
Re : C++ et exceptions [Résolu]
mais c'est particulier aux exceptions vu que le passage par référence "classique" a besoin que l'objet soit en mémoire pour marcher, non ?
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#16 Le 05/11/2008, à 20:34
- tiky
Re : C++ et exceptions [Résolu]
L'objet est toujours en mémoire... le compilateur fait une copie en mémoire de l'objet exception, je vois pas où il pourrait le mettre sinon.
3) http://jlecomte.ifrance.com/c++/c++-faq-lite/virtual-functions-fr.html
2) Ton cours ne le dit pas car c'est un mécanisme qui est transparent. Tu n'as pas à t'en soucier dans la plupart des cas.
1) Non c'est faux, tu dois lister les types d'exceptions...
void function( void ) throw ( e1, e2, ... );
Mais encore une fois c'est fortement déconseillé car ça met fin de façon brutale au programme. C'est utile seulement pour spécifier qu'une méthode ne doit jamais lever d'exception ( c'est le cas d'un destructeur ).
Dernière modification par tiky (Le 05/11/2008, à 20:40)
Conseil d'expert: il vous faut un dentifrice adapté...
Hors ligne
#17 Le 05/11/2008, à 20:46
- rniamo
Re : C++ et exceptions [Résolu]
dans :
void f() {
...
Exception e();
throw e;
}
try {
f();
}
catch(Exception& ex) {
// ici ex n'existe plus puisqu'il est passé par référence donc pas de copie, si ?
}
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#18 Le 05/11/2008, à 20:53
- tiky
Re : C++ et exceptions [Résolu]
Non c'est l'objet e qui n'existe plus, par contre une copie est créée et ex est une référence sur celui-ci. Tu peux vérifier en comparant les adresses mémoires de e et de ex.
Dernière modification par tiky (Le 05/11/2008, à 20:53)
Conseil d'expert: il vous faut un dentifrice adapté...
Hors ligne
#19 Le 05/11/2008, à 20:56
- rniamo
Re : C++ et exceptions [Résolu]
oui, le problème c'est pourquoi une copie avec les exception mais pas les autres passages par références ?
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#20 Le 05/11/2008, à 21:02
- Luc Hermitte
Re : C++ et exceptions [Résolu]
Je ne comprends pas ta question.
throw va déclencher une copie => il faut que cela soit copiable (relativement au type réel qui est connu au moment du throw)
Ensuite dans le catch, pour éviter de perdre le type réel, il faut attraper une référence, pas le choix. sinon, en copiant, tu perds le type dynamique (ce n'est qu'un cas particulier des règles qui disent que les classes polymorphes sont incompatibles avec les sémantiques de copie)
Hors ligne
#21 Le 05/11/2008, à 21:05
- tiky
Re : C++ et exceptions [Résolu]
Ah non, tu ne peux pas faire ceci par exemple:
A & function( void )
{
A foo;
return foo;
}
C'est exactement le même problème que pour les exceptions. L'objet foo est détruit lorsque la fonction est dépilée de la pile d'exécution. La référence retournée est donc invalide, le compilateur donne d'ailleurs un warning.
Tu peux faire ceci ( bien que ce soit idiot ):
A & function( void )
{
A * foo = new A;
return *foo;
}
Cette fois foo est dans le tas, il n'est pas détruit lorsque la fonction est dépilée, la référence reste valide. Il faut toujours faire attention à bien utiliser des références valides.
Dernière modification par tiky (Le 05/11/2008, à 21:07)
Conseil d'expert: il vous faut un dentifrice adapté...
Hors ligne
#22 Le 05/11/2008, à 21:16
- rniamo
Re : C++ et exceptions [Résolu]
donc c'est bien le "throw" qui implique qu'une copie est créé, ok, merci beaucoup (donc mon cours est faux puiqu'il dit que tout se passe comme un passage d'argument à une fonction)
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#23 Le 05/11/2008, à 21:33
- tiky
Re : C++ et exceptions [Résolu]
donc c'est bien le "throw" qui implique qu'une copie est créé, ok, merci beaucoup (donc mon cours est faux puiqu'il dit que tout se passe comme un passage d'argument à une fonction)
Bah c'est vrai que ça se passe comme l'argument d'une fonction, il s'agit d'un passage par valeur qui nécessite toujours une copie.
Conseil d'expert: il vous faut un dentifrice adapté...
Hors ligne
#24 Le 05/11/2008, à 21:39
- rniamo
Re : C++ et exceptions [Résolu]
??
pour moi passage par référence c'est passage par adresse avec la syntaxe du passage par valeur. Serait ce de la que vient mon erreur ?
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#25 Le 05/11/2008, à 21:45
- tiky
Re : C++ et exceptions [Résolu]
Une référence c'est un autre nom pour une même zone mémoire, il n'y pas de copie. C'est le seul cas dans lequel il n'y a pas de copie effectuée pour l'argument d'une fonction. Ton cours est inexacte si tu préfères mais c'est pas totalement faux que ça se passe comme pour le passage d'un argument, du moins pour les fonctions en C, c'est exact.
Dernière modification par tiky (Le 05/11/2008, à 21:54)
Conseil d'expert: il vous faut un dentifrice adapté...
Hors ligne