Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Nouveau membre du Club
    operator = implicitly deleted : Que faire ?
    Bonjour la comunauté,

    Je souhaite retirer (et détruire) un objet de la classe Objet d'un conteneur vector "listObjet" avec le code suivant (i est un unsigned int < listObjet.size()):
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
     
    listObjet.erase(listObjet.begin() + i);

    J'obtiens le message d'erreur suivant :

    error: use of deleted function 'Objet& Objet::operator=(const Objet&)
    'Objet& Objet::operator=(const Objet&)' is implicitly deleted because the default definition would be ill-formed

    Je reste perplexe sur le sens à donner à ces messages (et à ce qu'il faudrait faire pour remédier à la situation).
    Pourriez vous m'éclairer svp ?

    Rick.

  2. #2
    Expert confirmé
    Bonjour,

    Pour enlever un élément dans une table, le seul moyen et de copier les Objet pour combler le trou correspondant à l’élément disparaissant.
    Mais Objet est un objet non copiable, cette opération est donc impossible.

    Alors :
    a) il faut voir pourquoi Objet est non copiable et remédier en le rendant copiable
    b) ou ne pas utiliser un std::vector<Objet> mais plutôt un std::list<Objet>. Ce type de conteneur supporte de stocker des objets non copiables mais on y perdra des capacités (par exemple listObjet.begin()+i n'est pas possible.)
    c) ou utiliser un vector de pointeurs ou de std:reference_wrapper sur des Objet qui n'aura qu'à copier les pointeurs au lieu de la copie impossible des Objet.

    La solution (a) est peut-être préférable. Si tu ne vois pas pourquoi Objet n'est pas copiable donne nous la déclaration de Objet.

  3. #3
    Expert éminent sénior
    Salut,
    Citation Envoyé par dalfab Voir le message

    La solution (a) est peut-être préférable. Si tu ne vois pas pourquoi Objet n'est pas copiable donne nous la déclaration de Objet.
    Ben, rien qu'à voir le nom, j'aurais tendance à dire que Objet est une classe de base servant pour une multitude de classe dérivée (un God Object, en somme), ce qui justifierait sans doute pleinement qu'il ne soit pas copiable.

    Dans cette optique, je pencherais d'avantage pour la solution C

    Ceci étant dit, je suis particulièrement frileux à l'idée de créer une classe Objet destinée à servir de classe de base à toutes les autres, surtout en C++ (*), car il faut retenir que l'héritage multiple se doit de respecter le LSP, si bien que tous les services rendus par la classe de base (faisons simple : les fonctions publiques qu'elle exposent) doivent être valide pour l'ensemble des classes dérivées, y compris pour les classes ne dérivant de Objet que de manière (peut-être très) indirecte.

    Or, j'ai beau me creuser la cervelle, je n'arrive pas à imaginer un service qui sera valable à la fois pour un compte en banque et pour un animal, par exemple (et on pourrait étendre la liste à l'envi).

    (*) bien que je comprenne les motivations qui ont poussé les développeurs de java ou de C# à créer une telle classe, car c'est elle qui permet au ramasse miettes de fonctionner correctement. Comme il n'y a pas de ramasse miettes en C++, la seule raison plausible (bien que discutable) d'avoir une telle classe est purement et simplement nulle et non avenue
    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

  4. #4
    Nouveau membre du Club
    Tout d'abord merci pour ces réponses, elles éclairent le sujet.

    Effectivement je pense que la solution c, un vecteur de pointeur (smart bien sûr, probablement un vecteur de "unique_ptr") doit être une bonne solution.
    J'avais plus ou moins ça en tête mais avant de la mettre en œuvre, je voulais comprendre la raison de ces messages.

    Ma classe "Objet" (Objet est un pseudo en fait) n'est ni une classe mère ni une classe hérité.
    Cependant elle contient deux autres classes, elle est donc une composition.
    Peut être est-ce là la raison du fait qu'elle soit non copiable ?

    Le reste les attributs sont des int des bool, une enum class et des conteneurs vector et map.
    Je veux bien joindre les headers de ces classes mais j'ai peur qu'elles soient si maladroitement construites (je fais tout ça en autodidacte) que cela dissuade quiconque de s'y intéresser...
    En plus, je les modifie quotidiennement pour les optimiser au fur et à mesure de mes progrès en c++.

    Rick.

  5. #5
    Expert éminent sénior
    Citation Envoyé par Rick_Cplusplus Voir le message

    Ma classe "Objet" (Objet est un pseudo en fait) n'est ni une classe mère ni une classe hérité.
    Cependant elle contient deux autres classes, elle est donc une composition.
    Peut être est-ce là la raison du fait qu'elle soit non copiable ?
    Pas forcément, du moins, pas de manière directe.

    A priori, si tu obtiens un message de ce genre, c'est parce que la définition de ta classe ressemble à
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class Machin{
    public:
        Machin(Machin const &) = delete;
        Machin & operator = (Machin const &) = delete;
    };

    Mais, pour pouvoir copier une classe, il faut être capable... d'en copier le contenu. Si ta classe est une composition, et qu'elle prend la forme de
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class Machin{
    private:
        Brol leBrol;
        Bidule leBidule;
    };
    tu ne pourra -- forcément -- copier l'instance de la classe Machin que ... si tu peux copier les données membres leBrol et leBidule. Si, pour une raison ou une autre, la classe Brol ou la classe Bidule ne peut pas être copiée, il devient forcément impossible de copier la classe Machin.

    Et, bien sur, on peut remonter très loin comme cela, car, il se peut que tu ne puisse en réalité pas copier la classe Brol à cause ... d'une de ses données membre qui ne peut pas être copiée, et ainsi de suite jusqu'à n'en plus finir
    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

###raw>template_hook.ano_emploi###