//en cas de succès de ma fontion
//je créé un objet correspondant
if (h) objet = new MaClasse(h);
//en cas d'echec, je m'arrête là
else return;
Maintenant, je voudrais que ce soit ma classe qui s'occupe d'appeler
MaFonction(...) :
MaClasse *objet;
objet = new MaClasse(fichier);
//si echec alors je sors
if (objet == NULL) return;
Cela implique que dans le constructeur de ma classe, si MaFonction renvoie
0(echec) j'annule la construction de la classe et je renvoie NULL comme
pointeur, est-ce possible ?
La meme question se pose pour le destructeur :
Dans le destructeur, je dois appeler une fonction, si celle-ci echoue, je
voudrais que la destruction soit annulée, comment faire ?
//si echec alors je sors if (objet == NULL) return;
Tu ne peux pas. Le constructeur est appelé après l'allocation de mémoire.
Il faut remplacer ton constructeur par une méthode statique, qui n'appelle le constructeur que si tu es sur que la construction va réussir.
Sinon, tu peux penser aux exceptions. Il y a eu une discussion ici-même il n'y a pas longtemps.
-- Matthieu
kanze
"PurL" wrote in message news:<c24mgq$4am$...
Je dois faire ceci :
HANDLE h = MaFonction(fichier); MaClasse *objet;
//en cas de succès de ma fontion //je créé un objet correspondant if (h) objet = new MaClasse(h);
//en cas d'echec, je m'arrête là else return;
Maintenant, je voudrais que ce soit ma classe qui s'occupe d'appeler MaFonction(...) :
La solution habituelle dans ce cas-là est une fonction usine, c-à-d une fonction statique qui renvoie un pointeur à une instance nouvellement allouée.
MaClasse *objet; objet = new MaClasse(fichier);
//si echec alors je sors if (objet == NULL) return;
Cela implique que dans le constructeur de ma classe, si MaFonction renvoie 0(echec) j'annule la construction de la classe et je renvoie NULL comme pointeur, est-ce possible ?
Non. Des constructeurs n'ont pas de valeur de retour.
Selon le cas, on peut lever une exception dans le constructeur. Dans ce cas-là, on ne revient pas en séquence, le pointeur n'est jamais écrit, etc. Donc, quelque chose du genre :
MaClasse* p = NULL ; try { p = new MaClass( fichier ) ; } catch ( MonException& ) { }
pourrait faire l'affaire. Mais à mon avis, c'est lourd, et je ne vois pas d'avantage par rapport à une fonction usine.
La meme question se pose pour le destructeur : Dans le destructeur, je dois appeler une fonction, si celle-ci echoue, je voudrais que la destruction soit annulée, comment faire ?
Dans ce cas-là, impossible. Un destructeur n'échoit jamais. Même dans le cas où il lève une exception, l'objet est quand même « détruit ». Dans une expression de delete, par exemple, la mémoire serait libérée, exception ou non.
-- James Kanze GABI Software mailto: Conseils en informatique orientée objet/ http://www.gabi-soft.fr Beratung in objektorientierter Datenverarbeitung 11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
"PurL" <purl-nospam@chez.com> wrote in message
news:<c24mgq$4am$1@news-reader1.wanadoo.fr>...
Je dois faire ceci :
HANDLE h = MaFonction(fichier);
MaClasse *objet;
//en cas de succès de ma fontion
//je créé un objet correspondant
if (h) objet = new MaClasse(h);
//en cas d'echec, je m'arrête là
else return;
Maintenant, je voudrais que ce soit ma classe qui s'occupe d'appeler
MaFonction(...) :
La solution habituelle dans ce cas-là est une fonction usine, c-à-d une
fonction statique qui renvoie un pointeur à une instance nouvellement
allouée.
MaClasse *objet;
objet = new MaClasse(fichier);
//si echec alors je sors
if (objet == NULL) return;
Cela implique que dans le constructeur de ma classe, si MaFonction
renvoie 0(echec) j'annule la construction de la classe et je renvoie
NULL comme pointeur, est-ce possible ?
Non. Des constructeurs n'ont pas de valeur de retour.
Selon le cas, on peut lever une exception dans le constructeur. Dans ce
cas-là, on ne revient pas en séquence, le pointeur n'est jamais écrit,
etc. Donc, quelque chose du genre :
MaClasse* p = NULL ;
try {
p = new MaClass( fichier ) ;
} catch ( MonException& ) {
}
pourrait faire l'affaire. Mais à mon avis, c'est lourd, et je ne vois
pas d'avantage par rapport à une fonction usine.
La meme question se pose pour le destructeur :
Dans le destructeur, je dois appeler une fonction, si celle-ci echoue,
je voudrais que la destruction soit annulée, comment faire ?
Dans ce cas-là, impossible. Un destructeur n'échoit jamais. Même dans le
cas où il lève une exception, l'objet est quand même « détruit ». Dans
une expression de delete, par exemple, la mémoire serait libérée,
exception ou non.
--
James Kanze GABI Software mailto:kanze@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
//en cas de succès de ma fontion //je créé un objet correspondant if (h) objet = new MaClasse(h);
//en cas d'echec, je m'arrête là else return;
Maintenant, je voudrais que ce soit ma classe qui s'occupe d'appeler MaFonction(...) :
La solution habituelle dans ce cas-là est une fonction usine, c-à-d une fonction statique qui renvoie un pointeur à une instance nouvellement allouée.
MaClasse *objet; objet = new MaClasse(fichier);
//si echec alors je sors if (objet == NULL) return;
Cela implique que dans le constructeur de ma classe, si MaFonction renvoie 0(echec) j'annule la construction de la classe et je renvoie NULL comme pointeur, est-ce possible ?
Non. Des constructeurs n'ont pas de valeur de retour.
Selon le cas, on peut lever une exception dans le constructeur. Dans ce cas-là, on ne revient pas en séquence, le pointeur n'est jamais écrit, etc. Donc, quelque chose du genre :
MaClasse* p = NULL ; try { p = new MaClass( fichier ) ; } catch ( MonException& ) { }
pourrait faire l'affaire. Mais à mon avis, c'est lourd, et je ne vois pas d'avantage par rapport à une fonction usine.
La meme question se pose pour le destructeur : Dans le destructeur, je dois appeler une fonction, si celle-ci echoue, je voudrais que la destruction soit annulée, comment faire ?
Dans ce cas-là, impossible. Un destructeur n'échoit jamais. Même dans le cas où il lève une exception, l'objet est quand même « détruit ». Dans une expression de delete, par exemple, la mémoire serait libérée, exception ou non.
-- James Kanze GABI Software mailto: Conseils en informatique orientée objet/ http://www.gabi-soft.fr Beratung in objektorientierter Datenverarbeitung 11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
kanze
wrote in message news:...
[...]
La meme question se pose pour le destructeur : Dans le destructeur, je dois appeler une fonction, si celle-ci echoue, je voudrais que la destruction soit annulée, comment faire ?
Dans ce cas-là, impossible. Un destructeur n'échoit jamais. Même dans le cas où il lève une exception, l'objet est quand même « détruit ». Dans une expression de delete, par exemple, la mémoire serait libérée, exception ou non.
J'ajouterais que les compilateurs sont pas toujours conforme en ce qui concerne le comportement quand on quitte un destructeurs par une exception, et que cet comportement varie d'un compilateur à l'autre. Donc, par exemple, si je lève une exception dans un destructeur d'un objet dans un tableau, ni g++ ni Sun CC appelle des destructeurs sur les éléments non encore detruits, malgré §15.2 : « An objet that is partially constructed or partially destroyed will have destructors executed for all of its fully constructed subobjects, that is, for subobjects for which the constructor has completed execution and the destructor has not yet begun execution. » (Les éléments d'un tableau sont bien des sous-objets de l'objet qui est le tableau.) VC++ 6.0 fait correctement, mais néglige (comme les autres, d'ailleurs) à libérer la mémoire. Si la norme est moins claire en ce qui concerne la libération de la mémoire, c'est la seule interprétation raisonable, étant donné qu'on ne peut pas libérer la mémoire autrement.
Vue les erreurs dans ces compilateurs, c'est encore une raison de plus de ne jamais quitter un destructeur par une exception.
-- James Kanze GABI Software mailto: Conseils en informatique orientée objet/ http://www.gabi-soft.fr Beratung in objektorientierter Datenverarbeitung 11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
kanze@gabi-soft.fr wrote in message
news:<d6652001.0403032336.5703b43a@posting.google.com>...
[...]
La meme question se pose pour le destructeur : Dans le destructeur,
je dois appeler une fonction, si celle-ci echoue, je voudrais que la
destruction soit annulée, comment faire ?
Dans ce cas-là, impossible. Un destructeur n'échoit jamais. Même dans le
cas où il lève une exception, l'objet est quand même « détruit ». Dans
une expression de delete, par exemple, la mémoire serait libérée,
exception ou non.
J'ajouterais que les compilateurs sont pas toujours conforme en ce qui
concerne le comportement quand on quitte un destructeurs par une
exception, et que cet comportement varie d'un compilateur à l'autre.
Donc, par exemple, si je lève une exception dans un destructeur d'un
objet dans un tableau, ni g++ ni Sun CC appelle des destructeurs sur les
éléments non encore detruits, malgré §15.2 : « An objet that is
partially constructed or partially destroyed will have destructors
executed for all of its fully constructed subobjects, that is, for
subobjects for which the constructor has completed execution and the
destructor has not yet begun execution. » (Les éléments d'un tableau
sont bien des sous-objets de l'objet qui est le tableau.) VC++ 6.0 fait
correctement, mais néglige (comme les autres, d'ailleurs) à libérer la
mémoire. Si la norme est moins claire en ce qui concerne la libération
de la mémoire, c'est la seule interprétation raisonable, étant donné
qu'on ne peut pas libérer la mémoire autrement.
Vue les erreurs dans ces compilateurs, c'est encore une raison de plus
de ne jamais quitter un destructeur par une exception.
--
James Kanze GABI Software mailto:kanze@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
La meme question se pose pour le destructeur : Dans le destructeur, je dois appeler une fonction, si celle-ci echoue, je voudrais que la destruction soit annulée, comment faire ?
Dans ce cas-là, impossible. Un destructeur n'échoit jamais. Même dans le cas où il lève une exception, l'objet est quand même « détruit ». Dans une expression de delete, par exemple, la mémoire serait libérée, exception ou non.
J'ajouterais que les compilateurs sont pas toujours conforme en ce qui concerne le comportement quand on quitte un destructeurs par une exception, et que cet comportement varie d'un compilateur à l'autre. Donc, par exemple, si je lève une exception dans un destructeur d'un objet dans un tableau, ni g++ ni Sun CC appelle des destructeurs sur les éléments non encore detruits, malgré §15.2 : « An objet that is partially constructed or partially destroyed will have destructors executed for all of its fully constructed subobjects, that is, for subobjects for which the constructor has completed execution and the destructor has not yet begun execution. » (Les éléments d'un tableau sont bien des sous-objets de l'objet qui est le tableau.) VC++ 6.0 fait correctement, mais néglige (comme les autres, d'ailleurs) à libérer la mémoire. Si la norme est moins claire en ce qui concerne la libération de la mémoire, c'est la seule interprétation raisonable, étant donné qu'on ne peut pas libérer la mémoire autrement.
Vue les erreurs dans ces compilateurs, c'est encore une raison de plus de ne jamais quitter un destructeur par une exception.
-- James Kanze GABI Software mailto: Conseils en informatique orientée objet/ http://www.gabi-soft.fr Beratung in objektorientierter Datenverarbeitung 11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
PurL
La solution habituelle dans ce cas-là est une fonction usine, c-à-d une fonction statique qui renvoie un pointeur à une instance nouvellement allouée.
Je pourrais avoir un exemple ou un lien explicatif d'une fonction usine ? Pour le reste, j'ai compris la leçon, merci.
PurL
La solution habituelle dans ce cas-là est une fonction usine, c-à-d
une fonction statique qui renvoie un pointeur à une instance
nouvellement allouée.
Je pourrais avoir un exemple ou un lien explicatif d'une fonction usine ?
Pour le reste, j'ai compris la leçon, merci.
La solution habituelle dans ce cas-là est une fonction usine, c-à-d une fonction statique qui renvoie un pointeur à une instance nouvellement allouée.
Je pourrais avoir un exemple ou un lien explicatif d'une fonction usine ? Pour le reste, j'ai compris la leçon, merci.
PurL
Bonjour,
exemple:
class MaClasse { private: MaClasse(HANDLE h); ~MaClasse(); // 'virtual' si c'est une classe de base // ... public: // ...
// fonction usine static MaClasse* Construit(char const* fichier) { HANDLE h = MaFonction(fichier); return h ? new MaClasse(h) : 0; }
bool Detruit(/* ... */) { bool ok = ... ; if (ok) delete this; return ok; } };
int main() {
MaClasse* p = MaClasse::Construit("fichier.dat"); // ok
// utiliser p
/* HANDLE h = 0; p = new MaClasse(h); // erreur de compilation! delete p; // erreur de compilation ! */
if (p->Detruit(/*...*/)) // ok // detruit, ne plus utiliser p else // pas detruit, encore utiliser p // ... return 0; }
--
- Manuel to reply, swap the name with the domain.
Etienne Rousee
"Manuel" a écrit ...
if (ok) delete this;
Ah ! Je me posais la question. Ce n'est pas risqué de faire un delete this ? C'est un peu comme scier la branche sur laquelle on est assis, vu qu'on est encore dans le classe.
Etienne
"Manuel" <swissonline@mzaccaria.ch> a écrit ...
if (ok) delete this;
Ah ! Je me posais la question.
Ce n'est pas risqué de faire un delete this ?
C'est un peu comme scier la branche sur laquelle
on est assis, vu qu'on est encore dans le classe.
Ah ! Je me posais la question. Ce n'est pas risqué de faire un delete this ? C'est un peu comme scier la branche sur laquelle on est assis, vu qu'on est encore dans le classe.
Etienne
Manuel
"Etienne Rousee" a écrit dans le message de news:c27sjd$4fe$
"Manuel" a écrit ...
if (ok) delete this;
Ah ! Je me posais la question. Ce n'est pas risqué de faire un delete this ?
Oui, c'est risqué si on ne sait pas ce qu'on fait. Il ne faut pas accéder au membres de la classe, donnée ou fonctions, après un "delete this". Concrètement, c'est la "dernière" operation à faire.
C'est un peu comme scier la branche sur laquelle on est assis, vu qu'on est encore dans le classe.
Une fonction membre n'est pas "dans la classe" comme le serait une donnée membre... Après tout, ce n'est pas très différent de :
struct Classe { // ... };
bool Detruire(Classe* This) { bool ok = ...; if (ok) delete This; return ok; }
Le risque est le même ici si on deréférence le pointeur "This" après le "delete This", sinon c'est sans danger.
--
- Manuel to reply, swap the name with the domain.
"Etienne Rousee" <etienne.rousee@wanadoo.fr> a écrit dans le message de
news:c27sjd$4fe$1@news-reader5.wanadoo.fr...
"Manuel" <swissonline@mzaccaria.ch> a écrit ...
if (ok) delete this;
Ah ! Je me posais la question.
Ce n'est pas risqué de faire un delete this ?
Oui, c'est risqué si on ne sait pas ce qu'on fait.
Il ne faut pas accéder au membres de la classe,
donnée ou fonctions, après un "delete this".
Concrètement, c'est la "dernière" operation à faire.
C'est un peu comme scier la branche sur laquelle
on est assis, vu qu'on est encore dans le classe.
Une fonction membre n'est pas "dans la classe"
comme le serait une donnée membre...
Après tout, ce n'est pas très différent de :
struct Classe {
// ...
};
bool Detruire(Classe* This)
{
bool ok = ...;
if (ok) delete This;
return ok;
}
Le risque est le même ici si on deréférence le
pointeur "This" après le "delete This", sinon
c'est sans danger.
"Etienne Rousee" a écrit dans le message de news:c27sjd$4fe$
"Manuel" a écrit ...
if (ok) delete this;
Ah ! Je me posais la question. Ce n'est pas risqué de faire un delete this ?
Oui, c'est risqué si on ne sait pas ce qu'on fait. Il ne faut pas accéder au membres de la classe, donnée ou fonctions, après un "delete this". Concrètement, c'est la "dernière" operation à faire.
C'est un peu comme scier la branche sur laquelle on est assis, vu qu'on est encore dans le classe.
Une fonction membre n'est pas "dans la classe" comme le serait une donnée membre... Après tout, ce n'est pas très différent de :
struct Classe { // ... };
bool Detruire(Classe* This) { bool ok = ...; if (ok) delete This; return ok; }
Le risque est le même ici si on deréférence le pointeur "This" après le "delete This", sinon c'est sans danger.
--
- Manuel to reply, swap the name with the domain.
PurL
Merci pour ton intervention, cela est tres instructif.
PurL
Merci pour ton intervention, cela est tres instructif.
Merci pour ton intervention, cela est tres instructif.
PurL
kanze
"PurL" wrote in message news:<c27kml$2kv$...
La solution habituelle dans ce cas-là est une fonction usine, c-à-d une fonction statique qui renvoie un pointeur à une instance nouvellement allouée.
Je pourrais avoir un exemple ou un lien explicatif d'une fonction usine ? Pour le reste, j'ai compris la leçon, merci.
Achête-toi le livre « Design Patterns : Elements of Reusable Object-Oriented Sofware », de Gamma, Helm, Johnson et Vlissides (ISBN 0-201-63361-2). C'est un des must. (Il existe en traduction, mais d'après ce qu'on me dit, la traduction n'est pas très bonne.)
-- James Kanze GABI Software mailto: Conseils en informatique orientée objet/ http://www.gabi-soft.fr Beratung in objektorientierter Datenverarbeitung 11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
"PurL" <purl-nospam@chez.com> wrote in message
news:<c27kml$2kv$1@news-reader5.wanadoo.fr>...
La solution habituelle dans ce cas-là est une fonction usine, c-à-d
une fonction statique qui renvoie un pointeur à une instance
nouvellement allouée.
Je pourrais avoir un exemple ou un lien explicatif d'une fonction
usine ? Pour le reste, j'ai compris la leçon, merci.
Achête-toi le livre « Design Patterns : Elements of Reusable
Object-Oriented Sofware », de Gamma, Helm, Johnson et Vlissides (ISBN
0-201-63361-2). C'est un des must. (Il existe en traduction, mais
d'après ce qu'on me dit, la traduction n'est pas très bonne.)
--
James Kanze GABI Software mailto:kanze@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
La solution habituelle dans ce cas-là est une fonction usine, c-à-d une fonction statique qui renvoie un pointeur à une instance nouvellement allouée.
Je pourrais avoir un exemple ou un lien explicatif d'une fonction usine ? Pour le reste, j'ai compris la leçon, merci.
Achête-toi le livre « Design Patterns : Elements of Reusable Object-Oriented Sofware », de Gamma, Helm, Johnson et Vlissides (ISBN 0-201-63361-2). C'est un des must. (Il existe en traduction, mais d'après ce qu'on me dit, la traduction n'est pas très bonne.)
-- James Kanze GABI Software mailto: Conseils en informatique orientée objet/ http://www.gabi-soft.fr Beratung in objektorientierter Datenverarbeitung 11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
Etienne Rousee
a écrit ...
(Il existe en traduction, mais d'après ce qu'on me dit, la traduction n'est pas très bonne.)
Je la trouve pas si mauvaise que ça. Par contre, il y manque, me semble-t-il, le pattern "Mutation".
Etienne
<kanze@gabi-soft.fr> a écrit ...
(Il existe en traduction, mais d'après ce qu'on me dit,
la traduction n'est pas très bonne.)
Je la trouve pas si mauvaise que ça.
Par contre, il y manque, me semble-t-il, le pattern "Mutation".