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

Langage C++ Discussion :

initialisation automatique d'un vecteur comme membre d'une classe


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre actif
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Mai 2014
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2014
    Messages : 43
    Par défaut initialisation automatique d'un vecteur comme membre d'une classe
    J'ai une petite question :

    Dans le code qui suit, j'ai une classe Composant, et trois classe cercle rectangle et groupe qui en hérite.

    Je veux que mes groupe puissent contenir des composant j'ai donc un vecteur de pointeur sur des composant dans lequel je met les composants du groupe :

    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
     
    #ifndef DEF_COMPOSANT
    #define DEF_COMPOSANT
     
    #include <vector>
    #include <iostream>
    #include <string>
    using namespace std;
     
     
    class Composant {
     
    	public: virtual void ajoute(Composant * c) {}
    	public: virtual void affiche() = 0;
    	public: Composant(string nom) { this->nom = nom; }
    	public: virtual string getNom() { return this->nom; }
    	public: virtual ~Composant() {}
     
    	private: string nom;
    };
     
    class Cercle : public Composant {
     
    	public: Cercle(string nom) : Composant(nom) {}
    	public: void affiche() {
     
    		cout << "Cercle : " << this->getNom() << endl;
    	}
    };
     
    class Rectangle : public Composant {
     
    	public: Rectangle(string nom) : Composant(nom) {}
    	public: void affiche() {
     
    		cout << "Rectangle : " << this->getNom() << endl;
    	}
    };
     
    class Groupe : public Composant {
     
    	public: Groupe(string nom) : Composant(nom) {}
    	public: void ajoute (Composant * c) {
     
    		listeComposants.push_back(c);
    	}
    	public: void affiche() {
     
    		cout << "Groupe : " << this->getNom() << " contenant : " << endl;
    		for (int i = 0; i < listeComposants.size(); i++) {
     
    			listeComposants[i]->affiche();
    		}
    		cout << "----------- fin groupe " << this->getNom() << endl;
    	}
     
    	private: vector<Composant *> listeComposants;
    };
    #endif
    Vous avez peut être remarqué que je n'initialise jamais le membre listeComposant avec un new dans le constructeur de Groupe, et pourtant je ne rencontre aucun probleme, pourquoi ?

    voici le main que j'utilise pour tester le code :

    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
     
    #include "composant.h"
    using namespace std;
     
    int main() {
     
    	Cercle * c1 = new Cercle("C1");
    	Cercle * c2 = new Cercle("C2");
    	Rectangle * r1 = new Rectangle("R1");
    	c1->affiche();
     
    	Groupe * ga = new Groupe("GA");
    	ga->ajoute(c1);
    	ga->ajoute(r1);
    	ga->affiche();
    	Groupe * gb = new Groupe("GB");
    	gb->ajoute(ga);
    	gb->ajoute(c2);
    	gb->affiche();
    	delete c1;
    	delete c2;
    	delete r1;
    	delete ga;
    	delete gb;
    }

  2. #2
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Bonjour!

    espèce de javateux...
    new est a utiliser avec prudence et parcimonie

    ton main devrait être (avec un petit refactor sur l'affichage)

    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
    #include <iostream>
    #include "composant.h"
     
    using std::cout;
    using std::endl;
     
    int main() {
    	Cercle c1("C1");
    	Cercle c2("C2");
    	Rectangle r1("R1");
    	cout << c1<<endl;
     
    	Groupe ga("GA");
    	ga.ajoute(&c1);
    	ga.ajoute(&r1);
    	cout << ga << endl;
     
    	Groupe gb("GB");
    	gb.ajoute(&ga);
    	gb.ajoute(&c2);
    	cout << gb << endl;
     
    	return 0;
    }
    auquel cas, il faut que tu ajoute une surcharge de << pour chaque classe, plutot que affiche().
    quitte à paramétriser affiche avec le stream.

    Et tant qu'on y est, public: ou private: sont "ongoing": ils sont valables pour toutes les déclarations à suivre.

    La réponse a ta question, c'est que new fait une allocation mémoire spécifique, mais que toute variable est construite.
    Le constructeur d'une classe crée chacune de ses variables lors de la liste d'initialisation.

    Un exemple pour l'explication:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Bidule{
    public:
        const int constante;
        Bidule() : constante(0) {}
        Bidule(int i) : constante(i) {}
    };
     
    class ECHEC{
    public:
        const int constante;
        ECHEC(int i) {this->constante = i;}
    };
    ECHEC porte ce nom parce que le compilateur refusera le code. En effet, à l'ouverture de l'accolade, le membre constante aura déjà été créé et initialisé (avec la valeur par défaut des ints: 0)
    Du coup, dans le corps du constructeur, constante est déjà const.

    Le problème serait le même avec une référence.

    Pour ton vecteur, c'est la même chose: comme tu n'a rien précisé, le constructeur par défaut de vector a été appelé pendant l'initialisation.



    C++ n'est pas Java, ils ont des fonctionnements différents.
    Les objets sont déclarés et manipulés par valeur. Les références (et pointeurs) sont explicites.
    Tu ne devrais quasiment jamais avoir de pointeur dans ton code.
    A chaque fois que tu veux en écrire, demande toi pourquoi tu ne peux pas utiliser une référence.
    S'il n'y a pas de réponse c'est qu'il faut préférer cette dernière

  3. #3
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    J'oubliais:

    On ne dois pas polluer.

    Il ne peut pas y avoir de using namespace dans un en-tête, et il faut éviter tout using type.

    La raison est que tu ne sais pas comment ton code sera inclus, et que quelqu'un peut très bien définir une classe ou pire une variable globale portant un nom tiré du namespace.

  4. #4
    Membre actif
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Mai 2014
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2014
    Messages : 43
    Par défaut
    salut et merci pour la réponse très claire.

    il ne s'agit pas de mon code, il s'agit d'un vieux code d'un vieux livre sur c++ (c++98), peut etre est-ce pour ça.

    En tout cas, j'ai bien tout compris, sauf le coup du using dans l'en tête, je vais me renseigner sur ce que tu dis.

    eh oui bravo, j'ai été contraint de faire du Java (que je trouve ça beaucoup trop permissif et qui favorise les atrocités) pendant trop longtemps du coup je galère a reprendre les bon concept de C++ que j'avais pourtant je crois assimilé lorsque j'ai commencé le c++ il y a une quelques bonne années.


    Je me permettrait juste de justifier ma façon de déclarer mes membres public, private... je trouve que c'est pas élégant de mettre le même niveau d’indentation avec la classe et encore pire avec les membre, je ne me vois pas non plus le mettre entre les deux alors je les mets devant chaque déclaration.

  5. #5
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Hello,

    Juste une petite suggestion, n'étudie pas le c++ dans un manuel de 98, le langage a bcp évolué! Son créateur a dit lui-même que le c++11 semblait un langage différent. Tu passerais à côté de plein de bonnes choses, entre autres des pointeurs intelligents (std::unique_ptr et std::shared_ptr) qui permettent de créer un objet sur le tas sans gérer explicitement la désallocation.

    Bon courage pour la suite...

  6. #6
    Membre actif
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Mai 2014
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2014
    Messages : 43
    Par défaut
    merci pour la suggestion,

    mais si j'étudie avec ce vieux livre c'est parce que j'ai besoins de comprendre le cheminement qu'il y a eu dans l'histoire du langage, je chercherai ensuite un livre qui parle des éléments nouveaux parce que selon moi, en faisant de cette façon on comprend mieux pourquoi on utilise tel ou tel mécanisme, les raisons sous-jacentes aux différents élément qui composent le langage et donc on a une vue d'ensemble du langage qui permet une utilisation plus intuitive et plus significative quand on le place en tant qu'outils de création.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 14
    Dernier message: 16/11/2014, 21h58
  2. Réponses: 6
    Dernier message: 02/04/2008, 14h41
  3. Réponses: 2
    Dernier message: 30/01/2007, 16h55
  4. Réponses: 2
    Dernier message: 23/01/2007, 23h21
  5. Initialiser une référence membre d'une classe
    Par NicolasJolet dans le forum C++
    Réponses: 2
    Dernier message: 18/03/2006, 12h14

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