IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
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

C++ Discussion :

Comment copier correctement un attribut pointeur qui a des classes filles


Sujet :

C++

Vue hybride

Message pr�c�dent Message pr�c�dent   Message suivant Message suivant
  1. #1
    Membre confirm�
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    229
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 229
    Par d�faut Comment copier correctement un attribut pointeur qui a des classes filles
    Bonjour,

    je suis face � un probl�me objet et je n'arrive pas � trouver la solution, j'ai du trop faire de java et perdre quelques notions de polymorphisme
    En tout cas je "bloque" !!

    J'ai les classes suivantes :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    class TType {
    public:
    	int entier;
    };
     
    class TTypeA : public TType {
    public:
    	int entierA;
    	char * chaine;
     
    	TTypeA() {
    		entierA = 8;
    		chaine = "toto";
    	};
    };
     
    class TTypeB : public TType {
    public:
    	int entierB;
    };
     
    class TData {
    public:
    	TData(){};
     
    	int entierData;
    	TType * type;
    };
     
    class TDataFille : public TData {
    public:
    	int entierFille;
     
    	TDataFille(TData * data) {
    		this->entierData = data->entierData; // ok
    		this->type = new TType(); // comment dupliquer proprement, c'est à dire que la copie se fasse aussi au niveau de la classe fille instanciée???
    	}
    };
    et le code suivant :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
     
    	TData * data = new TData();
    	TTypeA *typeA = new TTypeA();
    	data->type = typeA;
    	TDataFille *fille = new TDataFille(data);
     
    et ailleurs :
    	TTypeA * a = (TTypeA*)fille->type;
    Je voudrais que a soit une parfaite copie de typeA, c'est � dire que l'attribut entierA vale 8 et que chaine vale "toto" (ce qui n'est pas le cas bien s�r avec le code ci dessus !)

    merci beaucoup pour votre aide, j'ai h�te de voir o� je bloque!!
    Pascale38

  2. #2
    Membre habitu�
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    D�cembre 2011
    Messages
    13
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : D�cembre 2011
    Messages : 13
    Par d�faut
    Il te faut une fonction virtuelle clone() dans ta classe de base et ses classes d�riv�es.


    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    class TType {
    public:
    	int entier;
    	virtual TType* clone() const { return new TType(*this); }
    };
     
    class TTypeA : public TType {
    public:
    	int entierA;
    	char * chaine;
     
    	TTypeA() {
    		entierA = 8;
    		chaine = "toto";
    	};
    
    	virtual TType* clone() const { return new TTypeA(*this); }
    };
     
    class TTypeB : public TType {
    public:
    	int entierB;
    	virtual TType* clone() const { return new TTypeB(*this); }
    };

  3. #3
    Membre confirm�
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    229
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 229
    Par d�faut
    et ensuite dans mon constructeur copie :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    
    TDataFille(TData * data) {
    	this->entierData = data->entierData;
    	this->type = data->type->clone();
    }
    trop trop fort, c'est beau !!
    Ca marche nickel !
    je n'avais jamais eu � utiliser clone() en fait jusqu'� pr�sent, je n'aurai donc jamais trouv� toute seule ! Comme quoi on en apprend toujours...
    merci beaucoup pour cette belle et super rapide r�ponse !!!
    Hop r�solu

    Pascale38

  4. #4
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Salut,

    Attention toutefois :


    A priori, une classe dont un membre serait un pointeur vers un objet polymorphe risque fort d'avoir une s�mantique d'entit�, et donc, de ne pas �tre plus copiable que le membre en question

    En effet, les objets polymorphes sont des types qui ont, syst�matiquement, s�mantique d'entit� et qui sont donc incompatibles avec la notion de copie (m�me s'il peuvent �tre cl�nables )

    Or, tu ne peux d�cemment envisager de copier un objet que si tu es en mesure... de copier correctement l'ensemble de ses membres :

    S'il y a un seul de ses membres que tu ne peux pas copier, tu ne pourras pas copier correctement ton objet

    Si, de plus, l'objet en question est d'un type polymorphe, tu as d'autant plus de raisons de le rendre non copiable!!!

    En outre, quand on parle de pointeur, on parle, de mani�re quasi syst�matique, de gestion dynamique de la m�moire "quelque part" autour du pointeur.

    si tu donne la responsabilit� de cette gestion dynamique de la m�moire � ton objet, tu prends une voie royale pour en arriver � ne pas respecter l'un des pilliers de la programmation qui est... la responsabilit� unique.

    En r�sum� :
    1. Commence d�j� par t'assurer qu'il est bel et bien coh�rent de rendre le membre cl�nable (ce qui peut etre rendu n�cessaire, par exemple, dans l'optique de la mise au point d'un m�canisme de undo / redo )
    2. S'il est coh�rent de rendre le membre clonable, inqui�te toi de savoir s'il est effectivement coh�rent de faire en sorte que ce soit ton objet qui ait la responsabilit� de ce clonage (l'id�al restant quand meme de veiller � ce que les objets ne soient pas clon�s "n'importe o�" )
    3. Enfin, si le membre en question est effectivement clonable et qu'il est effectivement coh�rent de donner la responsabilit� du clonage � ton objet (en sachant que, du coup, tu ne devrais plus lui donner d'autre responsabilit� ), alors, tu peux envisager de rendre ton objet �galement clonable (mais non copiable), pour autant que cela ait un sens de le faire
    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

  5. #5
    Membre confirm�
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    229
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 229
    Par d�faut
    Salut Koala01,
    hum l� j'avoue que tu d�passes et de loin mes connaissances en la mati�re, notamment lorsque tu parles d'avoir "une s�mantique d'entit�" ??

    Mon probl�me � la base est simplement que lorsque j'�cris :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    TData * data = new TData();
    TTypeA *typeA = new TTypeA();
    data->type = typeA;
    TDataFille *fille = new TDataFille(data);
     
    ...
     
    delete data;
    delete fille;
    je me retrouve avec un gros probl�me lors du delete de "data" et celui de "fille" car ils essayent tous les 2 de d�truire "typeA"... Mon id�e �tait donc de "cloner" typeA afin qu'il existe bien 2 instances et que chaque delete ai une instance � d�truire...

    Pascale38

  6. #6
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Citation Envoy� par Pascale38 Voir le message
    Salut Koala01,
    hum l� j'avoue que tu d�passes et de loin mes connaissances en la mati�re, notamment lorsque tu parles d'avoir "une s�mantique d'entit�" ??
    en gros:

    Il est possible de diviser l'ensemble des objets que tu vas manipuler en deux grandes cat�gories:

    1. Les (types d') objets ayant s�mantique de valeur et
    2. Les (types d') objets ayant s�mantique d'entit�.

    Quand un objet a s�mantique de valeur, tu peux parfaitement retrouver diff�rentes variables utilisant des adresses m�moire diff�rente mais pr�sentant la m�me ... valeur dans ton code sans que cela ne te pose de probl�me.

    C'est, par exemple, le cas des types primitifs (bon, ce ne sont pas des classes ) ou de la classe string.

    On pourrait dire qu'une classe ayant s�mantique de valeur est une classe pour laquelle il n'y a aucun besoin d'assurer une "unicit� identitaire".

    Si tu as une classe Couleur, Position ou encore Force, Pression, Puissance etc, les valeurs qui composent ce genre de classe suffisent pour pouvoir d�terminer une �galit� entre diff�rentes instances.

    Ce n'est, en effet, pas parce que tu as une couleur rouge quelque part que tu devras utiliser chaque fois la m�me instance de cette couleur pour la repr�senter

    A l'inverse, les objets ayant s�mantique d'entit� pr�sentent une obligation "d'unicit� identitaire", dans le sens o�, m�me si tu arrives � trouver deux objets dont l'ensemble des caract�ristiques sont identiques, il y aura toujours "quelque chose" qui permettra d'identifier une instance particuli�re de mani�re unique et non ambig�e (au minimum l'adresse m�moire � laquelle se trouve l'objet en question).

    Par exemple, tu pourrais trouver une voiture de m�me marque, de m�me mod�le, de m�me cylindr�e, avec les m�mes options et le m�me kilom�trage (aux centaines de m�tres pr�s) que la tienne sans que ce ne soit forc�ment la tienne:

    Tu ne pourras dire que c'est la tienne que si elle porte effectivement la m�me plaque d'immatriculation et le m�me num�ro de chassis ou, de mani�re plus simple encore, si... elle utilise la m�me adresse m�moire que la tienne

    Un autre exemple pourrait �tre celui d'un compte en banque : ce n'est pas parce que deux comptes en banque pr�sentent, � un instant T, le m�me solde que tu peux t'amuser � les m�langer et en arriver � une situation o� ton salaire serait vers� sur le compte de ton voisin, ou � une situation o� ton voisin effectuerait ses payements depuis le tien

    A partir de ces explications, on peut tirer un grand nombre de conclusions sur ce qui peut �tre fait (ou non) avec des objets ayant s�mantique de valeur et / ou avec des objets ayant s�mantique d'entit�, mais, les trois principales sont:
    1. Qu'un objet ayant s�mantique de valeur peut �tre copi� (vu qu'on peut trouver la m�me valeur � plusieurs adresses m�moire en m�me temps) alors qu'un objet ayant s�mantique d'entit� ne peut pas l'�tre (m�me une copie conforme de ta voiture ne serait pas TA voiture )
    2. Qu'un objet ayant s�mantique de valeur peut etre assign� alors qu'un objet ayant s�manbtique d'entit� ne peut pas l'�tre.
    3. Que deux objets ayant s�mantique de valeur peuvent �tre compar�s (par �galit�), alors qu'il n'y a aucun sens � permettre ce genre de comparaison avec les objets ayant s�mantique d'entit�

    Mon probl�me � la base est simplement que lorsque j'�cris :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    TData * data = new TData();
    TTypeA *typeA = new TTypeA();
    data->type = typeA;
    TDataFille *fille = new TDataFille(data);
     
    ...
     
    delete data;
    delete fille;
    je me retrouve avec un gros probl�me lors du delete de "data" et celui de "fille" car ils essayent tous les 2 de d�truire "typeA"... Mon id�e �tait donc de "cloner" typeA afin qu'il existe bien 2 instances et que chaque delete ai une instance � d�truire...
    Et ce serait une tr�s mauvaise id�e

    En effet, cela impliquerait que, une fois que tu aurais clon� ta donn�e, les deux objets qui manipulent la variable commune pourraient la faire �voluer de mani�re diff�rente, et peut etre de mani�re carr�ment incompatible entre elles...

    Lorsque tu voudrais r�cup�rer et manipuler cette donn�e, tu en arriverais donc tr�s rapidement � une situation o�, en fonction de l'objet au d�part duquel tu r�cup�res la donn�es, tu pourrait avoir un r�sultat diam�tralement oppos�

    Si je comprends ton principe, ton id�e vient, essentiellement, du fait que tu te trouves confront�e � un probl�me de conception majeur : tu n'as pas (encore) r�fl�chi � qui prend la responsabilit� de la dur�e de vie de ta donn�e

    De mani�re g�n�rale, il faut toujours garder en t�te le fait que, quand tu travailles avec des objets polymorphes, tu dois avoir un (et un seul !!!) type d'objet qui joue le role de "fournisseur" de l'objet polymorphe (et qui prend, entre autres, en charge la gestion de sa dur�e de vie ) et que tous les autres types d'objet qui pourraient manipuler cet objet polymorphe endossent le role "d'utilisateur" de l'objet.

    C'est � dire qu'ils peuvent utiliser l'objet � leur plus grande convenance, mais qu'il n'ont aucun droit sur sa dur�e de vie.

    Il n'est pas forc�ment n�cessaire de faire en sorte de centraliser la destruction de tous les objets polymorphes � un seul endroit, mais, en tout �tat de cause, il est indispensable de faire en sorte qu'il n'y ait qu'un type qui puisse d�cider de la destruction

    ainsi, on pourrait avoir une destruction "centralis�e, sous une forme proche de
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    class ObjectManager // à défaut d'autre terme, meme s'il est tendancieux ;)
    {
        public:
             // toadd peut avoir été créé "par ailleurs" ;)
            void add(MyPolyMorphicBase * toadd)
            {
                items_.push_back(toadd);
            }
            void remove(MyPolyMorphicBase * torem)
            {
                 for(auto it = items_.begin();
                       it != items_.end(); ++it)
                 {
                     if((*it) == torem)
                     {
                         delete (*it);
                         items_.erase(it);
                         return;
                     }
                 }
                 throw ElementNotFound();
            }
        private:
            std::vector<MyPolyMorphicBase * > items_;
    }
    ou quelque chose de "d�centralis�" (dans le sens o� ce n'est pas une instance unique d'un objet qui s'occupe de la destruction) sous une forme proche de
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    class MyPolyMorphicBase;
     
    class MyPolyMorphicHolder
    {
        public:
            // data a été créé "par ailleurs"
            MyPolyMorphicHolder(MyPolyMorphicBase * data):data_(data){}
            ~MyPolyMorphicHolder()
            {
                delete data_;
            }
        private:
            MyPolyMorphicBase * data_;
    };
    class MyHolderClass
    {
        public:
            MyHolderClass(MyPolyMorphicBase * data):hoder_(data){}
            ~MyHolderClass()
            {
                /* héhé... on ne fait rien ici, holder_ sera automatiquement détruit
                 * avec l'objet de type MyHolderClass, ce qui appellera..
                 * le destructeur de MyPolyMorphicHolder (et donc le delete sur data_) :D
                 */
            }
        private:
            MyPolyMorphicHolder holder_;
    };
    [EDIT]G�n�ralement, si tu en viens � envisager le fait que deux types diff�rents puissent devoir s'occuper de la destruction d'un objet polymorphe, c'est souvent le signe qu'il est plus que temps d'envisager de cr�er une classe qui aura seule cette responsabilit�
    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

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. Une classe pour mouler des instances qui soient des classes
    Par eyquem dans le forum G�n�ral Python
    R�ponses: 2
    Dernier message: 03/09/2009, 17h09
  2. R�ponses: 3
    Dernier message: 05/08/2009, 10h45
  3. R�ponses: 4
    Dernier message: 27/03/2008, 21h27
  4. R�ponses: 2
    Dernier message: 16/05/2007, 16h13
  5. R�ponses: 2
    Dernier message: 27/10/2006, 18h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo