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 :

Doute pour faire un constructeur/constructeur de copie


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2012
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2012
    Messages : 69
    Par défaut Doute pour faire un constructeur/constructeur de copie
    Bonsoir,

    J'ai un doute sur mes constructeurs vu que j'ai des pointeurs comme données membres et que je suis pas très doué en pointeurs.
    Quelqu'un peut-il m'aider ?

    J'ai ça dans mon header :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class MyClass
    {
    private:
      DWORD_PTR m_pToto;
     
    public:
      MyClass( );
      MyClass( const DWORD_PTR ptr );
      virtual ~MyClass( );
    };
    et j'ai ça comme constructeur et constructeur de copie dans le .cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    MyClass::MyClass( )
    {
      m_pToto = (DWORD_PTR) new CClassTruc();
      assert(m_pToto!= NULL);
    }
     
    MyClass::MyClass( const DWORD_PTR dwPtr )
    {
      m_pToto= (DWORD_PTR) new CClassTruc();
      m_pToto= dwPtr;
    }
    J'ai un gros doute sur mon constructeur de copie

    Merci.

    Bonne soirée.

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Déjà, MyClass( const DWORD_PTR ptr ); n'est pas la signature d'un constructeur par copie de MyClass. Une signature de construteur par copie pourrait être : MyClass( const MyClass &c );.

    Ensuite, la chose à faire dans ce constructeur dépend de la sémantique de ta classe. On ne peut pas deviner pour toi. Par contre, le code écrit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      m_pToto= (DWORD_PTR) new CClassTruc();
      m_pToto= dwPtr;
    va assigner une valeur à m_pToto, correspondant à de la mémoire juste allouée, puis l'écraser par une autre valeur juste après. Tu as donc du code inutile, et une fuite mémoire.

    Enfin, n'oublie pas dans les constructeurs d'utiliser de préférence les listes d'initialisation.

    Je te conseille de lire la section de la faq sur le sujet.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Membre confirmé
    Homme Profil pro
    Développeur .NET/C/C++
    Inscrit en
    Septembre 2007
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET/C/C++
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2007
    Messages : 71
    Par défaut
    Petite question:
    Pourquoi utilises-tu des DWORD_PTR?
    Ne serai-t-il pas préférable de les remplacer par des CClassTruc* ?

    Sinon, je plusoie JolyLoic: tu alloue de la mémoire et écrase le pointeur juste après, tu as donc une fuite mémoire.
    Ensuite, ce que dois faire ton constructeur de copie va surtout dépendre de ce que tu veux :
    - Soit tes 2 objets utilisent 2 instances différentes de la classe CClassTruc
    - Soit elles se partagent la même instance.

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2012
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2012
    Messages : 69
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Déjà, MyClass( const DWORD_PTR ptr ); n'est pas la signature d'un constructeur par copie de MyClass. Une signature de construteur par copie pourrait être : MyClass( const MyClass &c );.

    Ensuite, la chose à faire dans ce constructeur dépend de la sémantique de ta classe. On ne peut pas deviner pour toi. Par contre, le code écrit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      m_pToto= (DWORD_PTR) new CClassTruc();
      m_pToto= dwPtr;
    va assigner une valeur à m_pToto, correspondant à de la mémoire juste allouée, puis l'écraser par une autre valeur juste après. Tu as donc du code inutile, et une fuite mémoire.

    Enfin, n'oublie pas dans les constructeurs d'utiliser de préférence les listes d'initialisation.

    Je te conseille de lire la section de la faq sur le sujet.
    Ah oui bien sûr, je fais n'importe quoi.
    En fait mon problème est que je ne sais pas comment copier mon pointeur dans mon constructeur de copie.
    J'aurais bien envie de faire ça moi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    MyClass( const MyClass &c )
    {
      m_pToto = c.m_ptoto;
    }
    Mais je crois que ça ne va pas.
    Du coup je ferais bien ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    MyClass( const MyClass &c )
    {
      m_pToto= (DWORD_PTR) new CClassTruc();
      m_pToto = c.m_ptoto;
    }
    Mais là vous allez me dire que j'alloue de la mémoire et que je l'écrase aussitôt.
    Du coup je ne vois pas trop.

    Pourtant j'ai bien lu la faq ^^

    Citation Envoyé par bountykiler Voir le message
    Petite question:
    Pourquoi utilises-tu des DWORD_PTR?
    Ne serai-t-il pas préférable de les remplacer par des CClassTruc* ?

    Sinon, je plusoie JolyLoic: tu alloue de la mémoire et écrase le pointeur juste après, tu as donc une fuite mémoire.
    Ensuite, ce que dois faire ton constructeur de copie va surtout dépendre de ce que tu veux :
    - Soit tes 2 objets utilisent 2 instances différentes de la classe CClassTruc
    - Soit elles se partagent la même instance.
    Ah oui bien vu ^^
    En fait c'est parce que je suis en train de faire un wrapper et que ma ClassTruc ne doit pas être connue dans mon header
    parce que sinon mon programme qui contiendra un #include "MyClass" dépendra de MaClassTruc et il ne faut pas (dans mon cas).
    En fait MyClass encapsule la class ClassTruc et le seul moyen que j'ai trouvé c'est d'utiliser un DWORD_PTR pour manipuler MaClassTruc en 'anonyme'.

    Merci.

    Bonne journée.

  5. #5
    Membre confirmé
    Homme Profil pro
    Développeur .NET/C/C++
    Inscrit en
    Septembre 2007
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET/C/C++
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2007
    Messages : 71
    Par défaut
    Citation Envoyé par ZeNoob Voir le message
    J'aurais bien envie de faire ça moi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    MyClass( const MyClass &c )
    {
      m_pToto = c.m_ptoto;
    }
    Mais je crois que ça ne va pas.
    En fait si, tu peux. Tes 2 objects vont alors contenir chacun un pointeur vers une même variable (de type CClassTruc). Cela n'est pas mauvais en soit, mais le problème est qu'alors au moment de détruire une object, tu ne saura pas si tu doit faire un delete ou pas sur ce pointeur (car tu ne sais pas si tu est le dernier objet à pointer dessus ou pas).
    Une solution alors est d'utiliser des shared_ptr.

    [QUOTE]
    Du coup je ferais bien ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    MyClass( const MyClass &c )
    {
      m_pToto= (DWORD_PTR) new CClassTruc();
      m_pToto = c.m_ptoto;
    }
    Dans ce cas tu a 2 objects ont chacun un pointeurs vers des objets CClassTruc distints. Pour y arriver, tu dois plutot faire quelque chose d u style:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    MyClass::MyClass(const MyClass &c )
    {
      if(c.m_ptoto)//Ce teste m'evite de dereferencer un pointeur null
          m_pToto = (DWORD_PTR) new CClassTruc((CClassTruc)(*c.m_ptoto));
      else
        m_pToto = NULL;
    }

  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
    Salut,
    Citation Envoyé par ZeNoob Voir le message
    Ah oui bien vu ^^
    En fait c'est parce que je suis en train de faire un wrapper et que ma ClassTruc ne doit pas être connue dans mon header
    parce que sinon mon programme qui contiendra un #include "MyClass" dépendra de MaClassTruc et il ne faut pas (dans mon cas).
    En fait MyClass encapsule la class ClassTruc et le seul moyen que j'ai trouvé c'est d'utiliser un DWORD_PTR pour manipuler MaClassTruc en 'anonyme'.

    Merci.

    Bonne journée.
    Qu'est ce qui t'empêche d'utiliser la déclaration anticipée de la classe, et de travailler sur quelque chose comme
    MyClass.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class MaClassTruc ; // déclaration anticipée de la classe (cf lien ci dessus)
    class MyClass
    {
        public:
            MyClass() ;
            MyClass(MyClass const & c);
            ~MyClass();
            void foo() /* const */;
        private:
            MaClassTruc * ptr+;
    }
    MyClass.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <MaClassTruc.h> //car, ici, il faut, de toutes manière connaitre MaClassTruc ;)
    #include <MyClass.h>
    // j'ai fais le choix de copier le contenu du pointeur, parce qu'il semble plus cohérent ;)
    MyClass::MyClass():ptr_(0){}
    MyClass::MyClass(MyClass const & c):
        ptr_(c.ptr_? new MaClassTruc(*(c.ptr) : 0){}
    MyClass::~MyClass()
    {
        delete ptr_;
    }
    void MyClass::foo() /* const */
    {
        ptr_->doSomething();
    }
    Ta classe MyClass aura, de toutes manières, une dépendance vis à vis de MaClasseTruc, "simplement" du fait qu'elle va utiliser cette dernière en interne...

    Mais, parce que tu as recours à la déclaration anticipée, tu permet à l'utilisateur de MyClass de ne rien connaitre de MaClassTruc pour manipuler MyClass: tant que tu n'essaye pas de rajouter, dans MyClass, une fonction qui utilise explicitement un objet de type MaClasseTruc, l'utilisateur n'aura strictement aucune raison de s'intéresser à cette classe (autre, bien sur, que l'envie de savoir ce qui se cache "derrière le voile" )

    Mais ce sera, quoi qu'il en soit, toujours mieux que d'en venir à travailler avec des types comme DWORD_PTR (qui n'existe que sous windows ) ou (est-ce pire ce n'est en tout cas pas mieux ) avec des void * et de commencer à les transtyper à chaque fois
    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

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2012
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2012
    Messages : 69
    Par défaut
    Salut et merci à vous,

    Déjà j'ai mis de côté l'idée d'utiliser un DWORD_PTR, je vais déjà essayer de le faire 'normalement', on verra plus tard pour mon problème ...
    Ensuite j'ai compris (je crois) comment initialiser un pointeur avec le constructeur d'une classe
    mais alors pour les classes ou objets comme char* je ne sais pas trop comment faire hormis une simple recopie de pointeurs.

    J'ai cherché des exemples, lu la FAQ et tout, rien trouvé, alors j'ai écrit une exemple moi-même, sûrement avec des erreurs ...
    alors je vous mets mon code avec mes recopies de pointeurs, si y'a des trucs qui cloches n'hésitez pas !

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
     
    /**************** Fichier d'en-tête *****************/
     
    class CClassTest;
     
    class CMyCLass
    {
    protected:
    	char* 			m_pSzName;
    	CClassTest*		m_pTest;
     
    public:
    	CMyClass( );			// Constructeur par défaut.
    	virtual ~CMyClass( );		// Déstructeur.
     
    	CMyClass( const char* pSzName, const CClassTest* pTest );	// Constructeur.
    	CMyCLass( const CMyClass& myClass );						// Constructeur de recopie.
     
    	void		SetPtrName( char* pSzName );
    	void		SetPtrTest( CClassTest* pTest );
    	char*		GetPtrName( ) const { return m_pSzName; }
    	CClassTest* GetPtrTest( ) const { return m_pTest; }
    };
     
    /**************** Fichier cpp *****************/
     
    CMyClass::CMyClass( )
    {
    	m_pSzName	= NULL;
    	m_pTest		= NULL;
    }
     
    CMyClass::~CMyClass( )
    {
    	delete m_pSzName;
    	delete m_pTest;
    }
     
    CMyClass::CMyClass( const char* pSzName, const CClassTest* pTest )
    {
    	SetPtrName(pSzName);
    	SetPtrTest(pTest);
    }
     
    CMyClass::CMyCLass( const CMyClass& myClass )
    {
    	if ( myClass.m_pSzName == NULL )
    		m_pSzName = NULL
    	else
    		m_pSzName = myClass.m_pSzName;
     
    	if ( myClass.m_pTest == NULL )
    		m_pTest = NULL
    	else
    	{
    		delete m_pTest;
    		m_pTest = new CClassTest(*myClass.m_pTest);
    	}
    }
     
    void CMyClass::SetPtrName( char* pSzName )
    {
    	if ( pSzName == NULL )
    		m_pSzName = NULL;
    	else
    		m_pSzName = pSzName;
    }
     
    void CMyClass::SetPtrTest( CClassTest* pTest )
    {
    	if ( pTest == NULL )
    		m_pTest = NULL;
    	else
    	{
    		delete m_pTest;
    		m_pTest = new CClassTest(*pTest);
    	}
    }
    merci.

    Bonne journée.

Discussions similaires

  1. Réponses: 4
    Dernier message: 21/08/2007, 14h09
  2. Problème pour faire une copie de fichier.
    Par damien99 dans le forum C++
    Réponses: 1
    Dernier message: 12/02/2006, 16h37
  3. probléme pour faire une copie de base de donnée
    Par nours33 dans le forum MS SQL Server
    Réponses: 7
    Dernier message: 31/12/2005, 12h35
  4. [Conception][constructeur] pour faire un tableau
    Par vasilov dans le forum Collection et Stream
    Réponses: 6
    Dernier message: 20/07/2005, 10h58
  5. [xsl] xsl juste pour faire copie d'un xml
    Par peppena dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 17/02/2004, 16h17

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