En attendant unique_ptr<> (sic), comment empêche l'assignation et la copie d'un objet ?
Suffit-il de déclarer le copy constructor et l'operator= en private ?
En attendant unique_ptr<> (sic), comment empêche l'assignation et la copie d'un objet ?
Suffit-il de déclarer le copy constructor et l'operator= en private ?
Salut,
Une petite précision: il "suffit" de déclarer le constructeur par copie et l'opérateur d'assignation private, mais de ne surtout pas les définir
Autrement, tu placera certes une restriction à la copie et à l'assignation, mais tu ne l'interdira pas forcément![]()
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Pour forcer le linker à ne pas construire l'éxecutable ?
Plutôt pour forcer le linker à sortir sur une erreur si, par malheur, tu venais effectivement à invoquer un comportement de copie ou d'assignation
Car, si tu n'invoque jamais un comportement de copie ou d'assignation, bien que le compilateur ait estimé que ces comportements "existent", le linker ne se plaindra pas
Tout ce qui peut t'arrêter avant la période d'utilisation (AKA au moment de la compilation et / ou de l'édition de liens) est de nature à t'éviter des soucis parfois difficiles à résoudre en période d'utilisation![]()
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Si je passe par une nouvelle réponse, c'est parce que je prévois qu'elle va se transformer en roman...
Pour comprendre l'idée, considérons les choses depuis le début:
Si tu ne déclares pas l'un des "big fours" (constructeur, constructeur par copie, opérateur d'assignation et destructeur), le compilateur va les implémenter en accessibilité publique, ce qui les rend tout à fait accessibles de "n'importe où dans le code".
Si tu estimes qu'une classe ne peut pas être copiée ni / ou assignée, tu as tes raisons qui sont surement valables et qui n'ont pas à être remises en question.
Cependant, si tu déclares le constructeur par copie et / ou l'opérateur d'assignation en accessibilité privée et que tu les définis (que tu les implémente, si tu préfères), un code proche de
Le compilateur se plaindra parce que "le constructeur par copie est privé dans ce contexte"...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 void foo() { /* une instance "non copiée" */ MaClass mc: /* tu as oublié que MaClasse n'est pas sensée être copiable */ MaClass deux(mc); }
Tu as déjà avancé d'un grand pas
Mais si tu fais l'erreur dans une fonction membre de la classe, cela devient beaucoup plus dangereux...
Ainsi un code proche de
sera, non seulement accepté par le compilateur (après tout, MaClass(MaClass const&) est déclarée
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 void MaClass::doSomething() { /* tu oublie que ta classe n'est pas sensée etre copiable */ MaClass temp(*this); /*...*/ }) mais sera aussi acceptée par l'éditeur de lien (car le compilateur a bel et bien créé le code exécutable correspondant)...
Et, comme tu as surement des raisons pour avoir rendu ta classe non copiable, tu risque de te rendre compte du problème que... bien loin de l'invocation de doSomething...
La recherche de la raison pour laquelle ton instance de MaClass part en vrille deviendra une véritable galère... et occasionnera, au minimum un délais supplémentaire avant la remise du projet, au pire... le lancement d'une bombe atomique (allez, soyons sympa: un plantage lors de la démonstration de remise au client... ce qui fait quand même tache)
Par contre, si tu n'implémente pas le constructeur par copie et / ou l'opérateur d'affectation que tu as rendu privé(s), le linker te jettera lorsqu'il travaillera sur doSomething au motif qu'il rencontre uneC'est à dire, bien avant d'arriver chez le clientréférence indéfinie à <signes cabalistiques>MaClass(MaClass const&)<signes cabalistiques>
En plus, avec un peu de chance, il t'indiquera même dans quelle fonction tu dois aller chercher cet appel pour lequel il ne trouve aucun symbole
Tu sécurise donc à très peu de frais (et même en gagnant le temps de l'implémentation des deux méthodes) ta conception générale![]()
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Partager