Précédent   Forum du club des développeurs et IT Pro > C et C++ > C++ > Langage
Langage Langage C++, Programmation Orientée Objet, Templates, etc. Avant de poster : FAQ C++
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 03/01/2013, 17h21   #1
KosenHitatchi
Invité régulier
 
Inscription : juin 2010
Messages : 33
Détails du profil
Informations forums :
Inscription : juin 2010
Messages : 33
Points : 5
Points : 5
Par défaut Besoin d'aide pour comprendre l'appel au constructeur et destructeur de classe dans tableau d'objet

Bonjour a tous,

Je suis en train de coder un tableaux qui stocke des objet de classeD, a chaque ajout ce tableau s'elargit et stocke mon nouvel élément dans une nouvelle case.
Mais avant d'arriver a ce stade, je souhaite comprendre le comportement qui se produit actuellement dans mon programme (je fais ici un test avec un tableaux définis de base comportant une ligne et une colonne).

Voici mes fichiers :
classD.hpp
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef CLASSD_HPP
#define CLASSD_HPP
#include <string>
 
using namespace std;
 
class classD
{
    public:
        classD(const string myName = "classD");
        classD(const classD& aclassD);
        ~classD();
        string Getname() { return _name; }
        void Setname(string val) { _name = val; }
    private:
        string _name;
};
 
#endif // CLASSD_HPP
classD.cpp
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include "classD.hpp"
 
// Classe classD
 
classD::classD(const string myName){
        _name = myName;
        cout<<"Creation d'un objet de classD de nom : "<<_name<<endl;
}
 
classD::classD(const classD& aclassD){
    _name = aclassD._name;
}
 
classD::~classD(){
        cout<<"Destruction d'un objet de classD de nom : "<<_name<<endl;
    }; //destructeur
classT.hpp
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef CLASST_HPP
#define CLASST_HPP
#include "classD.hpp"
 
 
class classT
{
   public:
        classT(string name="");
        ~classT();
        classD** Get_tab2D() { return _tab2D; }
        void Set_tab2D(classD** val) { _tab2D = val; }
        int Getcolonnes() { return _colonnes; }
        void Setcolonnes(int val) { _colonnes = val; }
        int ajouterElement(const string aName = "ObjectD Tableau");
        classD retournerCase(const int colonne , const int ligne = 0 )const{return _tab2D[ligne][colonne];}
    private:
        classD** _tab2D;
        int _colonnes;
        int LIGNE;
};
 
#endif // CLASST_HPP
classT.cpp
Code :
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
#include <iostream>
#include "classT.hpp"
#include <string>
 
using namespace std;
 
classT::classT(string name)
{
    _colonnes = 0;
    LIGNE = 1;
    //_tab2D = new classD* [_colonnes];
    cout<<"creation objet classe T : "<<name<<endl;
}
 
classT::~classT()
{
    for (int i = 0; i< _colonnes;i++){
        delete _tab2D[i];
        cout<<"destruction objet classe T : colonne ["<<i<<"]"<<endl;
    }
    delete _tab2D;
    cout<<"destruction objet classe T "<<endl;
}
 
int classT::ajouterElement(const string aName){
    _colonnes++;
    classD aClassD(aName);
    _tab2D = new classD* [LIGNE];
    _tab2D[0] = new classD[_colonnes];
    _tab2D[0][0] = aClassD;
    return 0;
}
Et finalement mon fichier main

main.cpp
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include "fonctions.hpp"
 
int main()
{
//#########theme 3
cout<<endl<<"#########theme 3"<<endl<<endl;
//Tableau 2D
    classT monTabT("mon TabT");
    monTabT.ajouterElement("Mon premier objetTab1"); //il n'est possible de n'ajouter qu'un element du fait que _tab2D ne comporte pour l'instant qu'une case
    classD plop = monTabT.retournerCase(0,0);
    cout<<"recupere case[0][0] : "<<plop.Getname()<<endl;
 
    cout<<"-----Destruction instance de classe statique-----"<<endl;
 
    return 0;
 
}
Invite de commande
Citation:
#########theme 3

creation objet classe T : mon TabT
Creation d'un objet de classD de nom : Mon premier objetTab1 // creation de mon objet de type classD a stocker
Creation d'un objet de classD de nom : classD
Destruction d'un objet de classD de nom : Mon premier objetTab1 // destruction (pas normal)o_0 de mon objet de type classD a stocker
recupere case[0][0] : Mon premier objetTab1 // La destruction ci dessus n'a pas detruit l'objet stocker dans le tableau TabT
-----Destruction instance de classe statique-----
Destruction d'un objet de classD de nom : Mon premier objetTab1 // destruction de mon objet de type classD a stocker
Destruction d'un objet de classD de nom : Mon premier objetTab1 // destruction o_0 de mon objet de type classD a stocker
destruction objet classe T : colonne [0]
destruction objet classe T

Process returned 0 (0x0) execution time : 0.371 s
Press any key to continue.
Je ne comprend pas pourquoi le constructeur de la classeD est appeler plusieurs fois alors que seul un objet de type ClassD doit etre stocké dans le tableau.
Merci d'avance pour votre aide.
KosenHitatchi est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/01/2013, 18h25   #2
Bousk
Modérateur
 
Homme Cyrille
Network programmer
Inscription : juin 2010
Messages : 1 542
Détails du profil
Informations personnelles :
Nom : Homme Cyrille
Âge : 25
Localisation : France

Informations professionnelles :
Activité : Network programmer

Informations forums :
Inscription : juin 2010
Messages : 1 542
Points : 4 080
Points : 4 080
Bonjour,


le code
Code :
1
2
3
4
classD aClassD(aName);
    _tab2D = new classD* [LIGNE];
    _tab2D[0] = new classD[_colonnes];
    _tab2D[0][0] = aClassD;
Va
- créer aClassD
- créer _colonnes classD et faire autant d'appel au constructeur par défaut
- utiliser l'opérateur d'affection sur _tab2D[0][0] avec aClassD comme paramètre
- aClassD sera supprimé à la fin de la fonction
--> c'est une copie de aClassD qui a été affecté et survit dans le tableau
Bousk est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/01/2013, 18h30   #3
Iradrille
Membre éprouvé
 
Homme
Étudiant
Inscription : juin 2012
Messages : 263
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2012
Messages : 263
Points : 443
Points : 443
Tu devrais utiliser des vector au lieu de gérer toi même ton tableau.

Sinon,
Code :
1
2
3
4
5
6
7
8
int classT::ajouterElement(const string aName){
    _colonnes++;
    classD aClassD(aName); // création d'un objet classD
    _tab2D = new classD* [LIGNE];
    _tab2D[0] = new classD[_colonnes]; // création de _colonnes objets classD par defaut
    _tab2D[0][0] = aClassD; // operator=
    return 0; // suppression de aClassD
}
Ici tu crée un objet classD temporaire qui est détruit lorsque la fonction se termine.

Code :
1
2
classD retournerCase(const int colonne , const int ligne = 0 )const{return _tab2D[ligne][colonne];}
// création et retour d'une copie
De même quand tu récupères l'objet dans ton tableau, tu en récupères une copie.
Met un cout dans le constructeur par copie de classD ça apparaîtra plus clairement.

edit: correction de ma confusion entre operator= et construction par copie
Iradrille est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/01/2013, 20h51   #4
jo_link_noir
Invité régulier
 
Homme jonathan poelen
Étudiant
Inscription : juin 2011
Messages : 6
Détails du profil
Informations personnelles :
Nom : Homme jonathan poelen
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2011
Messages : 6
Points : 6
Points : 6
Salut,

lorsque que tu crées le tableau avec new, il y a autant de classD créer que de cellule dans le tableau, ici 1. Ensuite tu modifies la valeur de la première cellule en créant une nouvelle classD, ce qui fait 2 construction.

Sinon il y a plein de copie d'objet, notamment les std::string qui ne sont pas passés par référence constante.
Il en va de même pour le prototype de retournerCase qui gagnerait à retourner une référence constante
Code :
const classD& retournerCase(const int colonne , const int ligne = 0 )const;
Il y a aussi des fuites mémoire via une mauvaise utilisation de delete. Un new [] demande un delete [].
jo_link_noir est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/01/2013, 21h12   #5
KosenHitatchi
Invité régulier
 
Inscription : juin 2010
Messages : 33
Détails du profil
Informations forums :
Inscription : juin 2010
Messages : 33
Points : 5
Points : 5
Merci pour votre réponse je comprend mieux maintenant ce qui se passe dans le premier cas.
Par contre je ne comprend toujours pourquoi il y a une double destruction de l'objet D "Mon premier objetTab1 ".

Citation:
-----Destruction instance de classe statique-----
Destruction d'un objet de classD de nom : Mon premier objetTab1 // destruction de mon objet de type classD a stocker
Destruction d'un objet de classD de nom : Mon premier objetTab1 // destruction o_0 de mon objet de type classD a stocker
destruction objet classe T : colonne [0]
destruction objet classe T
Merci
KosenHitatchi est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/01/2013, 21h20   #6
Iradrille
Membre éprouvé
 
Homme
Étudiant
Inscription : juin 2012
Messages : 263
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2012
Messages : 263
Points : 443
Points : 443
retournerCase te retourne une copie de l'objet (que tu stockes dans plop)

Quand main retourne, plop et monTabT sont supprimés (monTabT détruit l'objet classD qu'il contient) -> 2 appels au destructeur.
Iradrille est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/01/2013, 10h46   #7
JolyLoic
Rédacteur/Modérateur
 
Avatar de JolyLoic
 
Homme Loïc Joly
Développeur informatique
Inscription : août 2004
Messages : 4 673
Détails du profil
Informations personnelles :
Nom : Homme Loïc Joly
Âge : 38
Localisation : France

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

Informations forums :
Inscription : août 2004
Messages : 4 673
Points : 9 887
Points : 9 887
Dans ce genre de code de test, ne jamais oublier d'instrumenter aussi le constructeur de copie...
__________________
Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
JolyLoic est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 04/01/2013, 16h25   #8
KosenHitatchi
Invité régulier
 
Inscription : juin 2010
Messages : 33
Détails du profil
Informations forums :
Inscription : juin 2010
Messages : 33
Points : 5
Points : 5
Merci pour votre aide, je vais regarder plus en détail mon constructeur de copie.
KosenHitatchi est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 21h15.


 
 
 
 
Partenaires

Hébergement Web