Bon, déjà, le test d'auto affectation (le if (this != & productionACopier) ) , tu peux le virer, car il ne sert à rien.
Ensuite, il existe quatre grandes fonctions "de base" si l'on s'en réfère à la forme canonique orthodoxe de Coplien:
Le constructeur par défaut
le constructeur de copie
l'opérateur d'affectation et
le destructeur
Sur ces quatre grandes fonctions, il existe une règle nommée "règle des trois grands" qui dit que si tu définis toi-même l'une des fonctions que sont le constructeur de copie, l'opérateur d'affectation ou le destructeur, alors, tu dois fournir la définition des trois.
Le truc, c'est que l'opérateur d'affectation et le constructeur de copie sont intimement liés, au point qu'un code proche de Type copy = objetExistant se traduira vraisemblablement par l'appel du constructeur de copie, et non par celui de l'opérateur d'affectation.
De plus, si l'on veut donner la sémantique d'entité à une classe, on se rend compte que l'on interdit aussi bien la copie que l'affectation
Enfin, on se rend compte que le code du constructeur de copie se trouve intégralement (à l'exception de la liste d'initialisation, qui n'existe pas pour l'opérateur d'affectation) dans l'opérateur d'affectation.
Du coup, le plus facile pour s'assurer que tout soit fait "dans l'ordre" (y compris la libération de la mémoire, le cas échéant), on a généralement recours à l'idiome "copy and swap" (copie et échange) pour implémenter l'opérateur d'affectation.
Le principe est simple et se fait en trois temps:
dans un premier temps, on va créer une copie (avec le constructeur de copie) de l'élément que l'on veut assigner à notre donnée
dans un deuxième temps, on va intervertir les données membres de la copie que l'on vient de créer avec celles de l'objet courant.
dans un troisième temps, on va ... renvoyer l'objet courant
Par facilité, nous créerons sans doute une fonction membre "swap(Type &)" qui se chargera d'intervertir les données membres d'un élément avec celles de l'élément courant. Elle prendra une forme proche de
void Production::swap(Production & other){
/* std::swap nécessite l'inclusion soit du fichier
* d'en-tête <algorithm> soit du fichier d'en-tête
* <utility>
*/
std::swap(m_tete, other.m_tete);
std::swap(m_corpProd, other m_corpProd);
}
et, grace à cela, ton opérateur d'affectation pourra ressembler à quelque chose "d'aussi simple" que
Production & operator=(Production const & other){
/* on crée la copie conforme de other */
Production copy{other};
/* on interverti les données membres de la copie
* et de l'objet courant
*/
swap(other);
/* on renvoie l'objet courant */
return *this;
} // la copie est automatiquement détruite ici
// ce qui implique que son destruteur est appelé
// et donc, a priori, que delete est bien appelé sur les
// pointeurs contenus par m_corpProd
NOTA:
1- Depuis maintenant sept ans, nous disposons dans la bibliothèque standard de pointeurs intelligents, dont std::unique_ptr (avant, on en disposait, mais il fallait utiliser boost)
Tu devrais vraiment t'intéresser à cette classe, car elle facilite énormément la vie.
2 a- Je ne sais pas à quoi correspond ton type enreg, dont fournis un plein tableau, mais, a priori, nous sommes sans doute en face d'une hiérarchie de classe avec ce type (et, plus précisément, de la classe de base qui a servi à construire cette hiérarchie). Si c'est le cas, le type enreg devrait avoir sémantique d'entité, ce qui voudrait dire que l'on ne veut surtout pas pouvoir copier les différentes instances que l'on a mis dans le tableau!!!
Il me semble donc plus qu'utile de réfléchir à la responsabilité prise par ta classe production: devient-elle le propriétaire légitime des éléments contenus dans le tableau (ce qui implique que celui qui a rempli ce tableau n'en est plus responsable une fois que tu as transmis le tableau à ton instance de production), ou n'en est-elle qu'un "utilisateur parmi d'autres" ???
Dans tous les cas, il semblerait que ta classe production soit également un candidat idéal à la sémantique d'entité. Et, dans ce cas, ce n'est pas redéfinir le constructeur de copie et l'opérateur d'affectation que tu dois faire, mais... les interdire, carrément...
2 b- En plus, si tu es effectivement dans le cadre d'une hiérarchie de classes, le fait de faire appel a new enregistrement(/* ... */ ) a de grandes chances de te faire n'importe quoi, à l'exception de ce que tu souhaites
3- Si le type enreg n'intervient pas dans une hiérarchie de classes, tu n'as aucune raison d'utiliser un tableau de pointeur. Mais, dans ce cas, tu peux laisser le compilateur générer son constructeur de copie et son opérateur d'affectation avec son implémentation par défaut, car tout se fera automatiquement
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
le but de ce code est d'avoir des enregistrement terminaux et non-terminaux (enregT et enregNT, qui dérivent de enreg) dans une collection hétérogène, à l'aide de vector, car je leur applique un traitement différends grâce aux méthodes virtuelles. ces collections sont appelées production.
le code que je propose fait en sorte que deux pointeurs de types qui dérivent enreg ne pointe pas sur le même objet tout en étant une copie.
il y aura un tableau qui est la table d'analyse d'un analyseur LL et contient des productions
pour écrire cette surcharge d'opérateur d'affectation, je me suis inspiré du cours C++ openclassroom, mais j'en suis au polymorphisme. Peut-être que plus loin dans ce cours j'en apprendrais plus sur ces pointeurs intelligent
sinon, j'ai ajouté la déclaration de l'oprateur= dans la classe production et ça ne me fait plus d'erreurs de compilation
C'est un pointeur qui a comme sémantique d'être l'unique propriétaire de la ressource associée, et qui détruit la ressource quand il est lui même détruit. Voir documentation : http://en.cppreference.com/w/cpp/memory/unique_ptr .
MathieuSerpa a écrit:
le but de ce code est d'avoir des enregistrement terminaux et non-terminaux (enregT et enregNT, qui dérivent de enreg) dans une collection hétérogène, à l'aide de vector.
le code que je propose fait en sorte que deux pointeurs de types qui dérivent enreg ne pointe pas sur le même objet tout en étant une copie.
Jette cette copie, elle n'a rien à faire là. Supprime la, elle devrait de toute façon être interdite.
MathieuSerpa a écrit:
pour écrire cette surcharge d'opérateur d'affectation, je me suis inspiré du cours C++ openclassroom, mais j'en suis au polymorphisme. Peut-être que plus loin dans ce cours j'en apprendrais plus sur ces pointeurs intelligent
Ce "cours" est une aberration, quelques recherches sur le forum t'expliqueront les raisons et te redirigeront vers des tutoriels corrects.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C