Bonjour,
je propose un ajout dans la faq "Quelles sont les différences fondamentales entre le constructeur d'une classe et sa méthode Init() ?"
Il est écrit qu'il existe 2 solutions.
J'en vois une troisième: le scope guard.
Bonjour,
je propose un ajout dans la faq "Quelles sont les différences fondamentales entre le constructeur d'une classe et sa méthode Init() ?"
Il est écrit qu'il existe 2 solutions.
J'en vois une troisième: le scope guard.
Où donc veux-tu en venir?
Il est écrit:Le scope guard est également une solution qui permet de régler ce problème (bien que ce ne soit pas fait pour ça à l'origine):Si init lève une exception, la mémoire (ou autres ressources) allouée pour t n'est jamais libérée
C'est que parfois (souvent même j'ai l'impression) on ne peut pas acquérir tout dès le constructeur.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 class ScopeGuard { public: ScopeGuard () : engaged_ (true) {} ~ScopeGuard () { if (engaged_) { /* libération des ressources ici */} } bool init( /* params */ ) { // initialisation et acquisition ici, avec une gestion correcte des allocations (et libération en cas d'échec) // si tout s'est bien passé engaged_ = true; return true; } private: bool engaged_; };
Si tu ne peux pas tout acquérir dès le constructeur, c'est que tu veux construire une voiture sans avoir fabriqué ou acheté le moteur.
Ce que tu ne peux pas avoir automatiquement, demande le en argument, et tout devient simple.
Si ce n'est pas encore le cas, raiie-le (*).
Si c'est encore impossible, je pense que l'architecture est mal pensée.
Je m'explique:
Si j'ai besoin d'initialiser quelque chose que j'ai déjà construit, dans quel état était-il?
Un objet est toujours dans un état connu et utilisable, il doit être construit ou ne pas être.
* tiens, je l'aime bien, mon néologisme
C'est pas une troisième méthode, c'est une implémentation particulière de init().
Qui peut rapidement poser des problèmes : si tu as plusieurs variables à initialiser, tu devras créer une variable bool pour chaque variable membre que tu veux initialiser, ce qui sera vite ingérable.
La solution, c'est le RAII, c'est à dire initialiser dans le constructeur (et comme le dit leternel, si c'est pas possible, voir s'il n'y a pas un problème de conception).
Et utiliser des pointeurs intelligents (voir pas de pointeur) pour les variables membres.
Par contre, il faudra quand même mettre à jour cette faq (en fait, l'ensemble de la faq) pour le C++11 (auto_ptr...)
@leternel: J'ai du mal à comprendre ton message...
Selon toi, il serait interdit de construire un objet partiellement puis de le remplir ensuite par aggregation? L'idiome scope guard n'a donc pas lieu d'être?
Pas interdit, le C++ est un langage permissif...
Mais non respectueux du RAII, donc moins sur, moins robuste, moins lisible, etc
L'approche C++ : le RAII
Architecture Logicielle & Développement - RAII !
Partager