OVH Cloud OVH Cloud

empecher un constructeur de ...construire

10 réponses
Avatar
Nicolas Aunai
salut,

j'ai un constructeur prenant un paramètre, est-il possible dans le
corps du constructeur de tester le paramètre et de faire échouer la
construction de l'objet après le test ? ou doit-on se contenter de
tester le paramètre avant d'appeler de constructeur (ce qui n'est pas
top du tout)

je pense aux exceptions... mais bon...

--
Nico,
http://astrosurf.com/nicoastro
messenger : nicolas_aunai@hotmail.com

10 réponses

Avatar
Drakkhen
Avatar
Alexandre
"Nicolas Aunai" a écrit dans le message de
news:
salut,

j'ai un constructeur prenant un paramètre, est-il possible dans le
corps du constructeur de tester le paramètre et de faire échouer la
construction de l'objet après le test ? ou doit-on se contenter de
tester le paramètre avant d'appeler de constructeur (ce qui n'est pas
top du tout)

je pense aux exceptions... mais bon...


ben oui je vois pas trop quoi faire d'autre. Si une exception est lancée
dans un constructeur, l'objet n'est je crois pas construit.

MonObj::MonObj(Mon Par)
{
if( MonPar est pas bon)
throw UneExceptionAMoiQueJAime;
ContinueAConstruire();
}


--
Nico,
http://astrosurf.com/nicoastro
messenger :



Avatar
Patrick Mézard
j'ai un constructeur prenant un paramètre, est-il possible dans le
corps du constructeur de tester le paramètre et de faire échouer la
construction de l'objet après le test ? ou doit-on se contenter de
tester le paramètre avant d'appeler de constructeur (ce qui n'est pas
top du tout)

je pense aux exceptions... mais bon...


Exactement.
http://www.gotw.ca/gotw/066.htm ("Constructor Failures") est intéressant à
ce sujet.

Patrick Mézard

Avatar
Nicolas Aunai
Patrick Mézard avait écrit le 14/02/2004 :


Exactement.
http://www.gotw.ca/gotw/066.htm ("Constructor Failures") est intéressant à
ce sujet.



ok merci des renseignements.

concernant les exceptions, lorsqu'on fait un projet, à quel moment
doit-on commencer la réflexion sur les classes d'exceptions, leur
hierarchie, organisation etc... doit-on s'en préoccuper dès l'étape de
conception, pendant le codage a proprement parler, ou plutot une fois
que tout est fait, on s'occupe de la gestion des exceptions ?

--
Nico,
http://astrosurf.com/nicoastro
messenger :

Avatar
Matthieu Moy
Nicolas Aunai writes:

salut,

j'ai un constructeur prenant un paramètre, est-il possible dans le
corps du constructeur de tester le paramètre et de faire échouer la
construction de l'objet après le test ?


Moi, je ferais une fonction statique que tu appelles à la place du
constructeur, qui renvoit un objet de ta classe, et qui ne fait le
"new" que si le test réussi.

Parce que si tu le fait dans le constructeur, le "malloc" est déjà
fait, c'est moins efficace.

--
Matthieu

Avatar
Patrick Mézard
salut,

j'ai un constructeur prenant un paramètre, est-il possible dans le
corps du constructeur de tester le paramètre et de faire échouer la
construction de l'objet après le test ?


Moi, je ferais une fonction statique que tu appelles à la place du
constructeur, qui renvoit un objet de ta classe, et qui ne fait le
"new" que si le test réussi.


De quel new parles-tu ?
Comment ferais-tu lorsque l'objet n'est pas instancié dynamiquement comme là
:

struct array
{
array(int size)
{
if(size<0)
throw std::invalid_argument("Size must be positive");
[...]
//Alloue le tableau et fait des trucs
}

[...]
}

int main()
{
array a(-1);
}

Parce que si tu le fait dans le constructeur, le "malloc" est déjà
fait, c'est moins efficace.


De quel malloc parles-tu ?

Patrick Mézard


Avatar
Patrick Mézard
Exactement.
http://www.gotw.ca/gotw/066.htm ("Constructor Failures") est intéressant
à


ce sujet.



ok merci des renseignements.

concernant les exceptions, lorsqu'on fait un projet, à quel moment
doit-on commencer la réflexion sur les classes d'exceptions, leur
hierarchie, organisation etc... doit-on s'en préoccuper dès l'étape de
conception, pendant le codage a proprement parler, ou plutot une fois
que tout est fait, on s'occupe de la gestion des exceptions ?


Ca dépend de ce que tu entends par "gestion des exceptions".
A partir du moment où tu admets que ton code va voir passer des exceptions,
il vaut mieux en tenir compte partout, ça évite les mauvaises surprises. Ca
veut dire de gèrer les ressources correctement avec de la RAII, d'établir et
de conserver tes invariants d'objets même et surtout en cas d'exceptions,
etc...

En ce qui concerne la manière d'organiser et de gèrer tes exceptions, c'est
au cas par cas. Dans le cas d'une bibliothèque très spécialisée (compression
d'image par exemple) on peut imaginer qu'une seule classe d'exception
contenant un code d'erreur soit suffisante, car le traitement de l'exception
sera lui aussi sommaire (est-ce que j'ai réussi à compresser ou pas, si non,
pourquoi, et ça s'arrête là). Maintenant, si les traitements sont plus
complexes, la hiérarchie d'exceptions sera à leur image. Mais dans ce cas,
cette hiérarchie se dessinera d'elle-même avec le reste du code, vu qu'elle
apportera des fonctionnalités au même titre que les autres classes. La
gestion d'erreur n'est pas quelque chose d'anodin, en marge du processus de
développement. Il me parait difficile de s'en occuper a posteriori.

Patrick Mézard


Avatar
Vladimir
j'ai un constructeur prenant un paramètre, est-il possible dans le
corps du constructeur de tester le paramètre et de faire échouer la
construction de l'objet après le test ? ou doit-on se contenter de
tester le paramètre avant d'appeler de constructeur (ce qui n'est pas
top du tout)

je pense aux exceptions... mais bon...

Le plus élégant serait de lancer une exception lors de la construction,

sinon une autre solution est de faire un delete this ( c'est pas très
élégant, mais ça peut parfaitement convenir dans certain cas .... )

Avatar
Matthieu Moy
"Patrick Mézard" writes:

De quel new parles-tu ?


Du "new" que tu fais si tu alloue l'objet dynamiquement.

Comment ferais-tu lorsque l'objet n'est pas instancié dynamiquement comme là


[...]

int main() {
array a(-1);
}


En effet, dans ce cas là, tu ne peux pas passer à coté de l'appel du
constructeur. Mais à ce moment là, je ne vois pas trop quelle
sémantique on peut donner à « faire échouer la construction de
l'objet ». Si tu peux écrire

array a(-1);
b = a;

Alors, quelle est la sémantique de « b = a » ?

Effectivement, avec des exceptions, on s'en sort, puisque la ligne « b
= a » n'est plus atteignable, mais à ce moment, c'est plus que la
création de l'objet qui échoue, c'est carrément tout le bloc
d'instruction qui utilise l'objet. (Mais ça répond peut être à la
question, je ne dis pas le contraire)

Reste à voir ce que voulais exactement le posteur original ...

--
Matthieu

Avatar
Patrick Mézard
int main() {
array a(-1);
}


En effet, dans ce cas là, tu ne peux pas passer à coté de l'appel du
constructeur. Mais à ce moment là, je ne vois pas trop quelle
sémantique on peut donner à « faire échouer la construction de
l'objet ».


C'est exactement le sujet du "Guru of the Week" cité dans ma première
réponse : un objet non construit n'existe pas, donc on ne peut pas
l'utiliser. C'est pourquoi le fameux idiome du "constructeur + init()"
dénoncé par Stroustrup dans TCPPL est moins robuste que l'utilisation
d'exceptions pour signaler des échecs de constructions.

Si tu peux écrire

array a(-1);
b = a;

Alors, quelle est la sémantique de « b = a » ?


Aucune. Cette instruction n'a de sens que si "a" est valide (ie. les
invariants d'objets sont valides). En cas d'échec à la construction de "a",
il ne peuvent l'être par définition.


Effectivement, avec des exceptions, on s'en sort, puisque la ligne « b
= a » n'est plus atteignable, mais à ce moment, c'est plus que la
création de l'objet qui échoue, c'est carrément tout le bloc
d'instruction qui utilise l'objet. (Mais ça répond peut être à la
question, je ne dis pas le contraire)

Reste à voir ce que voulais exactement le posteur original ...


Disons que je ne vois pas d'autre alternative. La technique du genre
"j'instancie une version incomplète mais destructible de l'objet, puis je
tente de l'initialiser et fait un return en cas d'échec" n'est pas
fondamentalement différente d'une levée d'exception. Elle est juste plus
complexe et plus fragile.

Patrick Mézard