Citation:
Envoyé par
koala01
Non: toujours par référence, sauf si tu as une bonne raison de faire autrement :
Toute la distinction référence/pointeur se fait sur la copiabilité/assignabilité du type.
Je ne vais pas déclarer des valeurs statiquement sur des attributs en sachant que je vais devoir traverser de multiples scopes alors que mes instances ne seront pas copiables/assignables.
Devant ça je suis obligé d'utiliser l'allocation dynamique pour des types non copiables pour qu'ils survivent.
Citation:
Encore faux :
constructeur par copie, opérateur d'affectation et destructeur obligatoires si l'implémentation fournie par défaut par le compilateur (comprends : celle que le compilateur fournira d'office si tu ne déclares pas ces fonctions) ne suffit pas.
Si tu dois donner une implémentation particulière à l'une de ces fonctions, tu devras le faire pour les trois (règle de "trois grands")
On est d'accord. Si je précisais de fournir ces constructeurs, c'est uniquement parce que C++ ne connait que la shallow-copy. Si je veux faire des deep-copies, je vais être oblig" de l'implémenter.
Une raison (bonne je ne sais pas) pourrait être de vouloir copier une instance d'entité pour justement ne pas la modifier.
On la copie, on fait des modifications, on obtient un résultat et on répète ceci avec la même instance de base.
Citation:
Les attributs sont bien privés, mais ce sont des valeurs, à moins que tu ne puisse pas faire autrement :
Si un de mes attributs est de type entité et qu'une instance d'entité est fournie au constructeur pour servir d'initialisation, je ne pourrai pas la copier.
Donc mon attribut doit recevoir une référence vers cette instance... pour ne pas dire pointeur (en conséquence du recours à de l'allocation dynamique évoqué plus haut)
Ceci vaut par extension à mes setters que je m’efforce d'éviter mais je ne vais pas non plus redéfinir des interfaces qui existent déjà (depuis quelques années pour certaines).
Si l'assignalibilité des entités était admise, je pourrais déréférencer mon pointeur et l'assigner à l'attribut (quoi que c'est peut-être une copie).
Citation:
En plus, un accesseur peut, éventuellement, se justifier si cela fait effectivement partie des services que tu es en droit d'attendre de la classe, mais un mutateur non : préfères fournir le nombre de fonctions qui vont bien et qui vont s'occuper elles-même de modifier ton membre de manière cohérente, en veillant à ce que leur nom indique clairement le genre de modification qui est faite.
Nous sommes d'accord.
Mes classes sont déjà écrites... les interfaces sont connues et elles comportent des setters.
Dans le futur je pourrai corriger ça mais dans l'état je me cantonne à ce qui existe un maximum.
Citation:
non: les collections membres sont toujours des valeurs
Le contenu des collections est, quant à lui, de préférence des valeurs, à moins que tu n'aies pas d'autre choix.
On parlait bien de la même chose, je me suis mal exprimé.
Il s'agit bien du contenu des collections qui est pointeur. Comme :
Code:
std::map<std::string, const std::string *>
Citation:
C'est parfois ce que tu veux, pour pouvoir passer la barrière imposée par la portée automatique des variables (qui n'existent autrement qu'entre le moment de leur déclaration et le l'accolade fermante de la portée dans laquelle elles sont déclarée).
C'est précisément pour ça que je parle de pointeur dans tout ce qui précède.
Le polymorphisme viendra surement plus tard, pour l'instant c'est uniquement les questions de scope.
Citation:
Mais, quoi qu'il en soit, tu ne doit jamais écrire une étoile, prendre l'adresse d'une variable ou écrire un new à la légère : Si tu viens à prendre la décision de le faire, c'est parce que tu as déterminé que c'était définitivement la meilleure chose à faire ;)
Ce sera surement la meilleure chose à faire parce que je serai bloqué par la rigidité des design pattern exposés.
Bonne fin d'après-midi.