Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
3030 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  excpetion dans le constructeur

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

excpetion dans le constructeur

n°1908761
Glock 17Pr​o
Posté le 27-07-2009 à 10:03:19  profilanswer
 

Hi,
 
Comment gérer proprement le cas, ou je détecte disons au milieu d'un constructeur, une erreur qui fait que je ne souhaite pas continuer la création de l'objet. Je peux faire un throw? Quelle est la meilleur technique ?  
 
Merci.

mood
Publicité
Posté le 27-07-2009 à 10:03:19  profilanswer
 

n°1908804
theShockWa​ve
I work at a firm named Koslow
Posté le 27-07-2009 à 10:51:34  profilanswer
 

faire une exception me semble tout à fait approprié, je ne crois même pas que tu aies vraiment d'autre solution.
Enfin, sur le projet sur lequel je bosse, on a désactivé les exceptions (pas dispo sur toutes les plateformes) donc on a une phase d'allocation (constructeur vide avec éventuellement des initialisations triviales) et une fonction de construction séparée, mais c'est pas trop la joie à utiliser
 
PS : tu n'aurais pas une légère dyslexie pour ton sujet ?
 
Edit : dans le chapitre 14.4.4 du Stroustrup, il précise que, pour une allocation standard, y'a pas de souci à lever une exception dans le constructeur, par contre, pour un new avec placement, c'est moins évident.


Message édité par theShockWave le 27-07-2009 à 10:56:49

---------------
last.fm
n°1908809
Glock 17Pr​o
Posté le 27-07-2009 à 10:59:43  profilanswer
 

merci, iou dsl pour le sujte j'ai tappé trop vtie

n°1908919
Taz
bisounours-codeur
Posté le 27-07-2009 à 13:41:56  profilanswer
 

Tu vas avoir un problème si tes membres construits n'ont pas de destructeurs. Par exemple:

Code :
  1. Foo() {
  2. this->p = new P;
  3. throw ...;
  4. }


la this->p ne sera pas détruite et sera perdu

n°1908931
Glock 17Pr​o
Posté le 27-07-2009 à 13:52:32  profilanswer
 

oui il faut que je fasse le boulot du destructeur moi même , et avant de lancer l'exception donc

n°1908944
Taz
bisounours-codeur
Posté le 27-07-2009 à 14:17:51  profilanswer
 

où alors tu te débrouilles pour ne travaillers qu'avec des smartpointers, des vectors, etc. C'est ça la vraie solution.

n°1908948
Glock 17Pr​o
Posté le 27-07-2009 à 14:20:09  profilanswer
 

dans ma boite ils sont obsédés par les perfs, l'expert en C++ de la boite, me déconseille même d'utiliser les exceptions,il préférerais dans le cas que j'ai exposé ici, un système de boolén, en gros une variable membre error , que je positionne à true si il y a eu un pbm dans le constructeur

Message cité 3 fois
Message édité par Glock 17Pro le 27-07-2009 à 14:20:21
n°1908950
Taz
bisounours-codeur
Posté le 27-07-2009 à 14:21:43  profilanswer
 

Glock 17Pro a écrit :

dans ma boite ils sont obsédés par les perfs, l'expert en C++ de la boite, me déconseille même d'utiliser les exceptions,il préférerais dans le cas que j'ai exposé ici, un système de boolén, en gros une variable membre error , que je positionne à true si il y a eu un pbm dans le constructeur


Pure folie.

n°1908954
Glock 17Pr​o
Posté le 27-07-2009 à 14:27:51  profilanswer
 

merci, ça me soulage, le mec a son statut d'expert, quand on est pas d'accord ça se termine,en euh je sais pas fait comme tu veux... wow ok d'accord

n°1909102
Joel F
Real men use unique_ptr
Posté le 27-07-2009 à 18:00:10  profilanswer
 

Glock 17Pro a écrit :

merci, ça me soulage, le mec a son statut d'expert, quand on est pas d'accord ça se termine,en euh je sais pas fait comme tu veux... wow ok d'accord


c'ets pas un expert :/ c'est tout

mood
Publicité
Posté le 27-07-2009 à 18:00:10  profilanswer
 

n°1911661
lambda0
Posté le 04-08-2009 à 15:36:43  profilanswer
 


Peut-être de vieux réflexes qui datent de l'époque où la gestion des exceptions n'était pas si fiable.
Je n'utilise pas non plus les exceptions dans les couches bas niveau d'un logiciel de calcul scientifique, surtout dans un constructeur, et on peut toujours s'en passer. Mais la technique de la variable membre 'error' citée plus haut est quand même peu élégante.
Je préfère les séquences du type :
...
objet = new Truc(parms1)
...
status = objet->Init(parms2)
if (status != NOERR)
{   delete objet;
    return status;
}
...
 
Séparer allocation et initialisation est une pratique tout à fait saine, même si celà parait compliquer un peu le code et demander un peu plus de rigueur.
Avis personnel: on devrait réserver l'usage des exceptions aux situations vraiment catastrophiques, genre échec d'allocation mémoire, pas pour gérer des paramètres non valides passés à un constructeur, ni non plus pour des erreurs mathématiques (divisions par 0, etc.), il s'agit là plutôt d'erreurs d'analyse.
Dans les couches de plus haut niveau, comme de l'interface utilisateur, je suis moins réticent à utiliser les exceptions, il n'y a pas trop de risque que ça dégrade les performances de façon visible.
 
A+
 

n°1911667
bjone
Insert booze to continue
Posté le 04-08-2009 à 15:57:08  profilanswer
 

Glock 17Pro a écrit :

dans ma boite ils sont obsédés par les perfs, l'expert en C++ de la boite, me déconseille même d'utiliser les exceptions,il préférerais dans le cas que j'ai exposé ici, un système de boolén, en gros une variable membre error , que je positionne à true si il y a eu un pbm dans le constructeur


 
Bah ça dépends.
Si il est anormal que la construction échoue (allocation, incohérence interne), exception.
Si ton objet a un état de validité interne variant, booléen interne. (J'en sais rien un objet qui maintiens je sais pas une connection à un truc hotplug par exemple, heu une webcam, un truc usb)


Message édité par bjone le 04-08-2009 à 15:58:36
n°1911951
Joel F
Real men use unique_ptr
Posté le 05-08-2009 à 13:06:46  profilanswer
 

lambda0 a écrit :


Séparer allocation et initialisation est une pratique tout à fait saine

 

Non car ca viole une bonne tripotée de principe objet dont la RAII ...
Si t'as une chance que qqn oublie ton init, bah tu es sur que qqn l'oubliera.
Un objet doit, des sa construction, etre utilisable en plein avec un comportement défini.

 

A la limite, si tu veut pas lancer d'exception dans un ctor, fait un ctor exception-safe :o

Message cité 2 fois
Message édité par Joel F le 05-08-2009 à 13:11:07
n°1911969
Taz
bisounours-codeur
Posté le 05-08-2009 à 13:44:32  profilanswer
 

lambda0 a écrit :


Peut-être de vieux réflexes qui datent de l'époque où la gestion des exceptions n'était pas si fiable.
Je n'utilise pas non plus les exceptions dans les couches bas niveau d'un logiciel de calcul scientifique, surtout dans un constructeur, et on peut toujours s'en passer. Mais la technique de la variable membre 'error' citée plus haut est quand même peu élégante.
Je préfère les séquences du type :
...
objet = new Truc(parms1)
...
status = objet->Init(parms2)
if (status != NOERR)
{   delete objet;
    return status;
}
...
 
Séparer allocation et initialisation est une pratique tout à fait saine, même si celà parait compliquer un peu le code et demander un peu plus de rigueur.
Avis personnel: on devrait réserver l'usage des exceptions aux situations vraiment catastrophiques, genre échec d'allocation mémoire, pas pour gérer des paramètres non valides passés à un constructeur, ni non plus pour des erreurs mathématiques (divisions par 0, etc.), il s'agit là plutôt d'erreurs d'analyse.
Dans les couches de plus haut niveau, comme de l'interface utilisateur, je suis moins réticent à utiliser les exceptions, il n'y a pas trop de risque que ça dégrade les performances de façon visible.
 
A+
 


 
Elle est collector ta réponse, je vais poster ça sur thedailywtf :)

n°1911979
lambda0
Posté le 05-08-2009 à 14:30:01  profilanswer
 

Joel F a écrit :


Non car ca viole une bonne tripotée de principe objet dont la RAII ...
Si t'as une chance que qqn oublie ton init, bah tu es sur que qqn l'oubliera.
Un objet doit, des sa construction, etre utilisable en plein avec un comportement défini.
 
A la limite, si tu veut pas lancer d'exception dans un ctor, fait un ctor exception-safe :o


 
C'est pour ça que j'ai précisé que celà demandait un peu de rigueur, pour ne pas oublier les Init().
Et même dans ce cas, je ne laisse pas les champs à des valeurs aléatoires : valeur numériques initialisées à 0 par exemple, tous les pointeurs à NULL.
Je préfère aussi les objets complètement initialisés à la construction, mais ce n'est pas toujours possible, et quand ça l'est, ça peut être pénalisant du point de vue des performances.
Exemple 1 : construction d'un tableau d'objets, chaque objet devant être initialisé avec des paramètres différents et nécessitant des allocations mémoires.
Exemple 2 : recyclage des objets pour optimiser la gestion de la mémoires. Un objet qui n'est plus utilisé n'est pas détruit mais est marqué comme disponible et réutilisé plus tard par un nouvel appel d'initialisation.
Ca fait une différence quand on manipule des tableaux de plusieurs millions d'objets (des entités géométriques dans mon cas)
 
Techniques adaptées aux couches bas niveau d'un logiciel, où on fait attention aux performances.
 

n°1912007
Joel F
Real men use unique_ptr
Posté le 05-08-2009 à 15:51:09  profilanswer
 

lambda0 a écrit :


C'est pour ça que j'ai précisé que celà demandait un peu de rigueur, pour ne pas oublier les Init().


Ta foi en l'etre humain est bien naive ...
 

lambda0 a écrit :


Et même dans ce cas, je ne laisse pas les champs à des valeurs aléatoires : valeur numériques initialisées à 0 par exemple, tous les pointeurs à NULL.
Je préfère aussi les objets complètement initialisés à la construction, mais ce n'est pas toujours possible, et quand ça l'est, ça peut être pénalisant du point de vue des performances.


Sauf que non
 

lambda0 a écrit :


Exemple 1 : construction d'un tableau d'objets, chaque objet devant être initialisé avec des paramètres différents et nécessitant des allocations mémoires.


Pattern factory + allocateur specifique pour std::container
 

lambda0 a écrit :


Exemple 2 : recyclage des objets pour optimiser la gestion de la mémoires. Un objet qui n'est plus utilisé n'est pas détruit mais est marqué comme disponible et réutilisé plus tard par un nouvel appel d'initialisation.


T'as le droit d'utiliser un appel direct au destructeur et un new de placement :o
 

lambda0 a écrit :


Techniques adaptées aux couches bas niveau d'un logiciel, où on fait attention aux performances.


Rien n'empeche de faire du bas niveau performant propre hein :o

n°1912602
sligor
Posté le 06-08-2009 à 22:02:51  profilanswer
 

Glock 17Pro a écrit :

dans ma boite ils sont obsédés par les perfs, l'expert en C++ de la boite, me déconseille même d'utiliser les exception


Il me semble avoir lu un article ou plusieurs disant que les exceptions doivent êtres utilisées pour des erreurs "inattendues" et donc les exceptions sont rares et n'ont donc aucun effet sur les performances. L'article disait que si une exception était appelé régulièrement c'est qu'elle est utilisée à mauvais escient et qu'un code de retour doit être utilisé, bien sur c'est pas possible pour un new  :D, mais si ton exception est exceptionnelle du coup c'est pas grave.
En résumé les perfs on s'en fout pour les exceptions.  :o

 

Il faudrait que je retrouve cet article  :fou:

Message cité 1 fois
Message édité par sligor le 06-08-2009 à 23:28:40
n°1912606
Joel F
Real men use unique_ptr
Posté le 06-08-2009 à 22:43:09  profilanswer
 

c'ets pas dans un GotW ?

n°1912661
Glock 17Pr​o
Posté le 07-08-2009 à 09:24:08  profilanswer
 

sligor a écrit :


Il me semble avoir lu un article ou plusieurs disant que les exceptions doivent êtres utilisées pour des erreurs "inattendues" et donc les exceptions sont rares et n'ont donc aucun effet sur les performances. L'article disait que si une exception était appelé régulièrement c'est qu'elle est utilisée à mauvais escient et qu'un code de retour doit être utilisé, bien sur c'est pas possible pour un new  :D, mais si ton exception est exceptionnelle du coup c'est pas grave.
En résumé les perfs on s'en fout pour les exceptions.  :o  
 
Il faudrait que je retrouve cet article  :fou:


 
moi je m'en sers également lorsque j'ai une fonction qui retourne un string par exemple , et qu'une erreur se produit, (ok je pourrais faire un argument output)

n°1913611
sligor
Posté le 10-08-2009 à 17:02:27  profilanswer
 

lambda0 a écrit :


[...] C'est pour ça que j'ai précisé que celà demandait un peu de rigueur, pour ne pas oublier les Init(). [...)


en relisant cet excellent livre: http://www.amazon.fr/Standards-pro [...] 2744071447

 

je suis tombé sur un article qui dit que cette méthode est très mauvaise car on fini par oublier d'appeler l'initialisation.

 

La solution:

 
Code :
  1. class Foo {
  2. protected:
  3. Foo(...){}  /* le contructeur est inaccessible de l'extérieur */
  4. void Initialize(...) /* l'initialisation est inaccessible de l'extérieur*/
  5. public:
  6. static shared_ptr<Foo> Create(...){  /* on crée des instances uniquement avec create*/
  7.    shared_ptr<Foo> p( new Foo);
  8.   p->Initialize(...);
  9.   return p;
  10. }
 

Au final le code appelant ne peut pas faire de new ou Initialize séparément, on est obliger d'appler le méthode statique "Create":

Code :
  1. shared_ptr<Foo> instance = Foo:Create(....)
 

J'ai simplifié l'exemple du livre qui lui utilise les templates pour éviter de redéfinir "create" pour les classes dérivées.

 

Au passage ta fonction Create peux gérer les cas d'erreurs, liberer p et retourner un code d'erreur par référence. L'auteur précise que cette méthode doit être utilisée uniquement en cas de nécessité. Dans l'example de l'article, le problème était qu'on ne peut pas appeler de fonctions virtuelles pures dans un contructeur en C++.

Message cité 3 fois
Message édité par sligor le 10-08-2009 à 17:03:17
n°1913624
Glock 17Pr​o
Posté le 10-08-2009 à 17:36:47  profilanswer
 


exact je l'ai sur le bureau :o, faudrait peut être que je lise plus souvent :$

n°1913627
sligor
Posté le 10-08-2009 à 17:39:28  profilanswer
 

c'est l'article 49 :)

n°1913631
masklinn
í dag viðrar vel til loftárása
Posté le 10-08-2009 à 17:48:10  profilanswer
 

Joel F a écrit :

Non car ca viole une bonne tripotée de principe objet dont la RAII ...


RAII est un principe C++, pas objet [:masklinn:1]


---------------
I mean, true, a cancer will probably destroy its host organism. But what about the cells whose mutations allow them to think outside the box by throwing away the limits imposed by overbearing genetic regulations? Isn't that a good thing?
n°1913650
Joel F
Real men use unique_ptr
Posté le 10-08-2009 à 18:38:29  profilanswer
 

masklinn a écrit :


RAII est un principe C++, pas objet [:masklinn:1]


pardon du raccourci.  
 
C'est pas ma faute si JAVA ne sait pas ce qu'est un destructeur :o

n°1913651
Joel F
Real men use unique_ptr
Posté le 10-08-2009 à 18:39:04  profilanswer
 

sligor a écrit :


La solution:
...
 


Je trouve ça moi beau qu'un objet RAII-fier

n°1913652
masklinn
í dag viðrar vel til loftárása
Posté le 10-08-2009 à 18:41:55  profilanswer
 

Joel F a écrit :

pardon du raccourci.

 

C'est pas ma faute si JAVA ne sait pas ce qu'est un destructeur :o


Oui enfin t'es bien gentil mais si pour toi "OO" ça donne le choix entre C++ et Java, on va pas aller bien loin [:masklinn:1]

 

Accessoirement Java a des destructeurs (finalizer), sauf qu'avec un GC non refcounting, ben l'appel du finalizer est pas déterministe, donc c'est pas d'un intérêt gigantesque [:masklinn:1]

 

Enfin, le destructeur n'est pas une notion générale de POO, c'est une notion spécifique à certaines implémentations de l'idée (et pas nécessairement les meilleures) [:masklinn:1]

Message cité 2 fois
Message édité par masklinn le 10-08-2009 à 18:45:24

---------------
I mean, true, a cancer will probably destroy its host organism. But what about the cells whose mutations allow them to think outside the box by throwing away the limits imposed by overbearing genetic regulations? Isn't that a good thing?
n°1913669
Glock 17Pr​o
Posté le 10-08-2009 à 19:35:24  profilanswer
 

masklinn a écrit :

 (et pas nécessairement les meilleures) [:masklinn:1]


non mais les moins pires alors  :ange:

n°1913694
Taz
bisounours-codeur
Posté le 10-08-2009 à 20:02:59  profilanswer
 

sligor a écrit :


en relisant cet excellent livre: http://www.amazon.fr/Standards-pro [...] 2744071447
 
je suis tombé sur un article qui dit que cette méthode est très mauvaise car on fini par oublier d'appeler l'initialisation.
 
La solution:
 

Code :
  1. class Foo {
  2. protected:
  3. Foo(...){}  /* le contructeur est inaccessible de l'extérieur */
  4. void Initialize(...) /* l'initialisation est inaccessible de l'extérieur*/
  5. public:
  6. static shared_ptr<Foo> Create(...){  /* on crée des instances uniquement avec create*/
  7.    shared_ptr<Foo> p( new Foo);
  8.   p->Initialize(...);
  9.   return p;
  10. }


 
Au final le code appelant ne peut pas faire de new ou Initialize séparément, on est obliger d'appler le méthode statique "Create":

Code :
  1. shared_ptr<Foo> instance = Foo:Create(....)



Tu te rends compte qu'au final Initialize de sert strictement à rien...

n°1913705
masklinn
í dag viðrar vel til loftárása
Posté le 10-08-2009 à 20:18:24  profilanswer
 

Glock 17Pro a écrit :


non mais les moins pires alors  :ange:


Alan Kay disagrees [:masklinn:1]


---------------
I mean, true, a cancer will probably destroy its host organism. But what about the cells whose mutations allow them to think outside the box by throwing away the limits imposed by overbearing genetic regulations? Isn't that a good thing?
n°1913726
Joel F
Real men use unique_ptr
Posté le 10-08-2009 à 21:37:46  profilanswer
 

masklinn a écrit :


Oui enfin t'es bien gentil mais si pour toi "OO" ça donne le choix entre C++ et Java, on va pas aller bien loin [:masklinn:1]  


 
Désolé de travailler avec des vrais trucs et pas des langages exotiques dont personne ne se sert :o
 

Spoiler :


Un troll se cache ici, sauras-tu le découvrir :o


n°1913735
Glock 17Pr​o
Posté le 10-08-2009 à 21:48:39  profilanswer
 

Taz a écrit :

Tu te rends compte qu'au final Initialize de sert strictement à rien...


lol

n°1913747
sligor
Posté le 10-08-2009 à 22:12:32  profilanswer
 

Taz a écrit :

Tu te rends compte qu'au final Initialize de sert strictement à rien...


 [:biiij]

n°1913796
budlite
Fresh
Posté le 11-08-2009 à 08:00:12  profilanswer
 

Taz a écrit :

Tu vas avoir un problème si tes membres construits n'ont pas de destructeurs. Par exemple:

Code :
  1. Foo() {
  2. this->p = new P;
  3. throw ...;
  4. }


la this->p ne sera pas détruite et sera perdu


J'imagine que avant le throw, il y a surement un IF, dans ce cas si on fait un delete dans ce meme bloc juste avant le throw, ca pourrait marcher nan ?

Code :
  1. Foo() {
  2. this->p = new P;
  3. if ( yaUneCouille ) {
  4. delete this->p;
  5. throw ...;
  6. }
  7. }



---------------
Fresh
n°1913819
Glock 17Pr​o
Posté le 11-08-2009 à 09:11:01  profilanswer
 
n°1913824
budlite
Fresh
Posté le 11-08-2009 à 09:18:47  profilanswer
 


Bah probleme réglé alors :D
En fait j'ai du mal a voir les cas ou ca devrait etre plus compliqué que ca ( car apparemment ca fait débat :o )


---------------
Fresh
n°1913839
Joel F
Real men use unique_ptr
Posté le 11-08-2009 à 09:43:35  profilanswer
 

bah cas ou une exception se propage depuis l'interieur d'une fonction appelée dans le constructeur et qui acquiere des ressources non triviales.
 
Reste ensuite le pb du constructeur incomplet etc...

n°1913843
Glock 17Pr​o
Posté le 11-08-2009 à 09:50:44  profilanswer
 

Joel F a écrit :


Reste ensuite le pb du constructeur incomplet etc...


 
c'est à dire ? même avec le if, on a un problème qui persiste ?

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  excpetion dans le constructeur

 

Sujets relatifs
C++ pointeur, constructeur, attributsclasse abstraite et constructeur
[C++] Utiliser le pointeur this dans le constructeurtemplate de déclaration d'un copy-constructeur en friend (combo \o/)
[java] super class et constructeur[java] classe abstraire, constructeur sans argument
Constructeur d'objets immutable & PatternErreurs dans mon constructeur ou ma fonction membre
Exception dans un constructeur puis traitement dans une autre classeSurcharge de constructeur en PHP
Plus de sujets relatifs à : excpetion dans le constructeur


Copyright © 1997-2025 Groupe LDLC (Signaler un contenu illicite / Données personnelles)