excpetion dans le constructeur - C++ - Programmation
Marsh Posté le 27-07-2009 à 10:51:34
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.
Marsh Posté le 27-07-2009 à 13:41:56
Tu vas avoir un problème si tes membres construits n'ont pas de destructeurs. Par exemple:
Code :
|
la this->p ne sera pas détruite et sera perdu
Marsh Posté le 27-07-2009 à 13:52:32
oui il faut que je fasse le boulot du destructeur moi même , et avant de lancer l'exception donc
Marsh Posté le 27-07-2009 à 14:17:51
où alors tu te débrouilles pour ne travaillers qu'avec des smartpointers, des vectors, etc. C'est ça la vraie solution.
Marsh Posté le 27-07-2009 à 14:20:09
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
Marsh Posté le 27-07-2009 à 14:21:43
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.
Marsh Posté le 27-07-2009 à 14:27:51
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
Marsh Posté le 27-07-2009 à 18:00:10
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
Marsh Posté le 04-08-2009 à 15:36:43
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+
Marsh Posté le 04-08-2009 à 15:57:08
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)
Marsh Posté le 05-08-2009 à 13:06:46
lambda0 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
Marsh Posté le 05-08-2009 à 13:44:32
lambda0 a écrit : |
Elle est collector ta réponse, je vais poster ça sur thedailywtf
Marsh Posté le 05-08-2009 à 14:30:01
Joel F a écrit : |
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.
Marsh Posté le 05-08-2009 à 15:51:09
lambda0 a écrit : |
Ta foi en l'etre humain est bien naive ...
lambda0 a écrit : |
Sauf que non
lambda0 a écrit : |
Pattern factory + allocateur specifique pour std::container
lambda0 a écrit : |
T'as le droit d'utiliser un appel direct au destructeur et un new de placement
lambda0 a écrit : |
Rien n'empeche de faire du bas niveau performant propre hein
Marsh Posté le 06-08-2009 à 22:02:51
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 , mais si ton exception est exceptionnelle du coup c'est pas grave.
En résumé les perfs on s'en fout pour les exceptions.
Il faudrait que je retrouve cet article
Marsh Posté le 07-08-2009 à 09:24:08
sligor a écrit : |
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)
Marsh Posté le 10-08-2009 à 17:02:27
lambda0 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 :
|
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 :
|
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++.
Marsh Posté le 10-08-2009 à 17:36:47
sligor a écrit : |
exact je l'ai sur le bureau , faudrait peut être que je lise plus souvent :$
Marsh Posté le 10-08-2009 à 17:48:10
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
Marsh Posté le 10-08-2009 à 18:38:29
masklinn a écrit : |
pardon du raccourci.
C'est pas ma faute si JAVA ne sait pas ce qu'est un destructeur
Marsh Posté le 10-08-2009 à 18:39:04
ReplyMarsh Posté le 10-08-2009 à 18:41:55
Joel F a écrit : pardon du raccourci. C'est pas ma faute si JAVA ne sait pas ce qu'est un destructeur |
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
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
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)
Marsh Posté le 10-08-2009 à 19:35:24
ReplyMarsh Posté le 10-08-2009 à 20:02:59
sligor a écrit :
|
Tu te rends compte qu'au final Initialize de sert strictement à rien...
Marsh Posté le 10-08-2009 à 20:18:24
Glock 17Pro a écrit : |
Alan Kay disagrees
Marsh Posté le 10-08-2009 à 21:37:46
masklinn a écrit : |
Désolé de travailler avec des vrais trucs et pas des langages exotiques dont personne ne se sert
Spoiler : |
Marsh Posté le 10-08-2009 à 21:48:39
ReplyMarsh Posté le 10-08-2009 à 22:12:32
ReplyMarsh Posté le 11-08-2009 à 08:00:12
Taz a écrit : Tu vas avoir un problème si tes membres construits n'ont pas de destructeurs. Par exemple:
|
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 :
|
Marsh Posté le 11-08-2009 à 09:18:47
Glock 17Pro a écrit : obviously |
Bah probleme réglé alors
En fait j'ai du mal a voir les cas ou ca devrait etre plus compliqué que ca ( car apparemment ca fait débat )
Marsh Posté le 11-08-2009 à 09:43:35
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...
Marsh Posté le 11-08-2009 à 09:50:44
Joel F a écrit : |
c'est à dire ? même avec le if, on a un problème qui persiste ?
Marsh Posté le 27-07-2009 à 10:03:19
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.