Bonjour.

Ce sujet fait suite à un échange lancé par cette question, qui n'avait plus rien à voir avec le sujet d'origine...
Je crée donc un topic séparé.

Donc, on dispose d'une hiérarchie de classes en héritage public.
Elles ont très certainement une sémantique d'entité, et donc ne sont ni copiables (ne possèdent pas de constructeur par copie (accessible)) ni assignable (ne possèdent pas d'opérateur d'affectation (par copie) (accessible)).

Je ne voyais pas vraiment pourquoi jusqu'à cette remarque, qui pointe un problème de cohérence.
Sans doute parce que je considérais qu'une classe doit être pleinement responsable des attributs membre qu'elle définit.
Peut-être une vision un peu trop stricte...
Bref.


Si l'on veut tout de même copier un objet d'une telle hiérarchie, on peut utiliser le design pattern « clone », dixit la F.A.Q..
Mais cela implique que les constructeurs par copie existent, bien que protégés ou privés.
Dans ce cas, à quoi faut-il faire attention lors de l'écriture de ces constructeurs, pour être sûr de rester correct et cohérent ?
Est-ce que les constructeurs par copie « par défaut » peuvent convenir ?

Maintenant que l'on a vu la copie, la question de l'assignation se pose.
Est-ce incorrect de se dire : « Je ne veux plus que cette variable représente cet objet, dorénavant elle représentera cet autre objet. » ?
Si la variable en question est un pointeur, un delete suivi d'une affectation au résultat de clone() sur l'objet adéquat fait l'affaire.
Mais sinon ?
Peut-on envisager une fonction membre clone() qui prendrait en paramètre l'adresse à laquelle dupliquer l'objet, ou une référence sur l'objet cible, et qui utiliserait l'opérateur d'affectation ?
Si oui, même question que précédemment.


Voyons à présent le déplacement.
Il n'y a pas de raison qu'une classe non copiable ne supporte pas le déplacement, n'est-ce pas ?
J'imagine que l'on pourrait se contenter du constructeur par déplacement et de l'opérateur d'affection par déplacement par défaut, mais on risque de se retrouver confronté au problème de cohérence indiqué par la remarque citée plus haut.
Alors comment faut-il faire ?


Passons maintenant à l'échange.
Ce n'est pas parce qu'une classe n'est pas copiable qu'elle n'est pas échangeable, si ?
L'implémentation « par défaut » de l'échange passe par le constructeur par copie et l'opérateur d'affectation.
Dommage...
Pour le C++11, c'est le constructeur par déplacement et l'opérateur d'affectation par déplacement.
Dommage également...

Du coup, je me pose les mêmes question que précédemment...
Surtout qu'il y a deux cas à gérer : si on utilise l'idiome « copy and swap » pour l'opérateur d'affectation ou non...


Voilà.
J'espère que vous pourrez m'aider à y voir un peu plus clair.