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 :

Question à propos de virtual method et de Vector


Sujet :

C++

  1. #1
    Membre extrêmement actif
    Avatar de Ryu2000
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2008
    Messages
    9 827
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2008
    Messages : 9 827
    Points : 18 750
    Points
    18 750
    Par défaut Question à propos de virtual method et de Vector
    Bonjour.

    Pour faire simple j'ai une classe mère appelé Mere et des classes filles appelées Fille1, Fille2 et Fille3.

    Je veux que Mere force ses filles à implémenter methode1(void) et methode2(void).

    Donc dans Mere.h j'ai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public :
         virtual methode1(void) = 0;
         virtual methode2(void) = 0;
    A un moment je veux un vector remplit de Fille1, Fille2, Fille3.
    Et un truc très important aussi, je ne veux faire aucun free et aucune allocation de mémoire.

    A la base j'avais pas les Filles et je faisais avec un Vector de Mere du coup je pouvais faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    vector <Mere> listeMere;
    ...
    Mere m1(5.0,1.3);
    listeMere.push_back(m1);
    Mais comme là j'ai des méthodes virtual, je suis obligé d'utilisé des pointeurs.
    J'ai vu que ça parlait d'un shared_ptr.

    Du coup j'ai fais ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    static vector <shared_ptr<Mere>> listeMere;
    ...
    listeMere.push_back(shared_ptr<Mere> m1(new Fille1(i, 5)));
    Bon le truc chiant c'est que j'ai du changer des . en ->.
    Mais sinon c'est correct ?

    Dans le principe, c'est propre ?
    C'est performant ?

    Parce que là je peux faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    listeMere[0]->methode1();
    Et si listeMere[0] est une Fille1 ça appelle bien Fille1.methode1(); donc ça fonctionne.

    Niveau mémoire j'ai quelque chose à gérer ?

    Ou alors existe il une autre solution pour avoir un vecor de mere est pouvoir appeler methode1 et methode2 dans n'importe quelle fille ?
    Parce qu'en Java j'aurais dis que Mere est une interface et les Filles implements Mere ou un truc comme ça, il me semble que c'est ça parce qu'en disant que t'implements tu dois forcer à implémenter les méthodes de l'interface mère.

    Apparemment shared_ptr ça ralentit pas mal.
    Si vraiment faut j'utilise les pointeurs tant pis, je ferais des free...

    Si vous avez des indications à me donner merci de me les indiquer.
    Au revoir.

    Edit :
    Finalement c'est aussi lent avec des pointeurs normaux.

    Edit :
    J'ai juste à appelé delete() et c'est bon ?
    Je fais comment :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    delete listeMere[i];
    listeMere.erase(listeMere.begin()+i);
    ?

    Sinon c'est utile les shared_ptr ?

  2. #2
    Membre éprouvé
    Homme Profil pro
    R&D imagerie 3D / prog embarquée
    Inscrit en
    Mars 2007
    Messages
    417
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : R&D imagerie 3D / prog embarquée
    Secteur : Santé

    Informations forums :
    Inscription : Mars 2007
    Messages : 417
    Points : 1 248
    Points
    1 248
    Par défaut
    Salut,

    Citation Envoyé par thierrybenji Voir le message
    Dans le principe, c'est propre ?
    à mon avis, oui c'est propre.

    Citation Envoyé par thierrybenji Voir le message
    C'est performant ?
    Ca dépend toujours de ton contexte, mais à mon avis on peut mieux faire. Tout d'abord parce qu'à chaque fois que tu sort un objet de ton vecteur, tu devra copier ton shared_ptr, donc incrémenter ton compteur de référence. Puis quand ces shared_ptr seront détruit, il faudra décrémenter ton compteur de ref, vérifier s'il tombe à 0 et éventuellement détruire (ce qui n'arrive pas avant que ton vecteur soit vidé ou détruit)
    Si ton vecteur est, par exemple, encapsulé dans une classe et représente une composition (et non une agrégation), j'y mettrais plutôt des pointer et je gèrerais les désallocations manuellement. Ca évite de prendre le overhead de la gestion des shared_ptr.

    Citation Envoyé par thierrybenji Voir le message
    Niveau mémoire j'ai quelque chose à gérer ?
    Non, le shared_ptr gére pour toi.

    Citation Envoyé par thierrybenji Voir le message
    Ou alors existe il une autre solution pour avoir un vecor de Mere est pouvoir appeler methode1 et methode2 dans n'importe quelle fille ?
    Si tu veux dire en mettant directement des Mere dans le vecteur, je ne pense pas que ça soit possible. Comme tu le sais surement déjà, pour utiliser le polymorphisme en C++ tu dois travailler soit avec des pointers, soit avec des références.
    Ce problème vient entre autre du fais que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sizeof(Mere) != sizeof(Fille1)
    Donc, si tu allou sur la stack une Mere, tu n'aura surement pas la place d'y mettre une fille. Le problème s'étend facilement au vecteur. Si ce dernier contient des Mere, alors la taille de chaque cellule de ce dernier sera de sizeof(Mere). Impossible d'y coller une Fille1. Par contre, une référence ou un pointer fait toujours la même taille.
    Une des conséquences de tout ça, c'est qu'il n'y aura aucun lookup dans la table des fonctions virtuelles si tu appelle une fonction sur autre chose qu'un pointer ou une réf.

  3. #3
    Membre extrêmement actif
    Avatar de Ryu2000
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2008
    Messages
    9 827
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2008
    Messages : 9 827
    Points : 18 750
    Points
    18 750
    Par défaut
    Merci beaucoup pour vos réponses.

    Donc shared_ptr gère la mémoire mais est un peu moins performant.

    Et si je veux utiliser des pointeurs normaux, lorsque j'enlève un objet du vector je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    vector <Mere*> listeMere;
    ...
    listeMere.push_back(new Fille1());
    ...
    delete listeMere[i];
    listeMere.erase(listeMere.begin()+i);
    C'est le destructeur de la classe mère qui est appelé mais je pense que ça fonctionne comme ça.
    Là niveau mémoire j'ai bien libéré la mémoire de l'objet stocké dans le vector ?
    Il ni a rien a écrire dans le destructeur ?

    Ça semble beaucoup plus pratique que les malloc et les free.

  4. #4
    Membre éprouvé
    Homme Profil pro
    R&D imagerie 3D / prog embarquée
    Inscrit en
    Mars 2007
    Messages
    417
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : R&D imagerie 3D / prog embarquée
    Secteur : Santé

    Informations forums :
    Inscription : Mars 2007
    Messages : 417
    Points : 1 248
    Points
    1 248
    Par défaut
    Citation Envoyé par thierrybenji Voir le message
    Là niveau mémoire j'ai bien libéré la mémoire de l'objet stocké dans le vector ?
    Il ni a rien a écrire dans le destructeur ?
    Exact, sauf que vector n'est en fait qu'un tableau dynamique, donc si tu fais beaucoup de "erase" autre que sur le "end" de ton vector, tu as mal choisi ton container, car pour retirer un élément, tu dois déplacer tous ceux qui suivent.
    Le problème ne se pose plus si tu détruit tout d'un coup. En premier tu itére sur ton vecteur et tu delete chaque objet, puis tu appelle "clear" sur ton vector.

    Pour ce qui est du destructeur, tu appelle bien celui de Mere, mais il devrait être déclaré virtuel, ce qui appellera celui des différentes FilleX selon le type de l'objet pointé.

  5. #5
    Membre extrêmement actif
    Avatar de Ryu2000
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2008
    Messages
    9 827
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2008
    Messages : 9 827
    Points : 18 750
    Points
    18 750
    Par défaut
    Merci.

    Ah oui, il faut déclarer le destructeur comme virtual, purée j'ai pas refais de C++ depuis des années j'ai perdu le truc.
    Mais j'imagine que ça ne change pas grand chose, puisqu'il ni a rien dans le destructeur et que les classes filles n'ont pas plus de variable que la classe mère, en fait elles implémentent juste deux méthodes.

    Quel Container serait mieux adapté ?

    En fait je remplit une liste au début et petit à petit je la vide.
    Je supprime les objets de la liste totalement dans le désordre.
    C'est plutôt aléatoire.

    Je réalise un Space Invaders en utilisant OpenGL :
    [ame="http://www.youtube.com/watch?v=ewbshlA_Ke4"]http://www.youtube.com/watch?v=ewbshlA_Ke4[/ame]

    Les monstres, les murs, les tirs tout est stocké dans des vector.

  6. #6
    Membre éprouvé
    Homme Profil pro
    R&D imagerie 3D / prog embarquée
    Inscrit en
    Mars 2007
    Messages
    417
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : R&D imagerie 3D / prog embarquée
    Secteur : Santé

    Informations forums :
    Inscription : Mars 2007
    Messages : 417
    Points : 1 248
    Points
    1 248
    Par défaut
    Citation Envoyé par thierrybenji Voir le message
    purée j'ai pas refais de C++ depuis des années j'ai perdu le truc.
    Héhé, je comprend tout à fait

    Citation Envoyé par thierrybenji Voir le message
    Quel Container serait mieux adapté ?
    Bien comme ça c'est difficile à dire. Je ne connais pas toutes tes contraintes. Je ne sais même pas ce que ton vecteur doit contenir. La suppression d'un élément aléatoire ne doit pas être la seule opération que tu fais sur ton container. Donc, choisir uniquement sur ce critère n'est vraiment pas optimal.
    Après, pour l'insertion séquentielle, tu es toujours à O(1) pour les containers non-ordonnés et O(log(N)) pour les ordonnés.
    Par contre, ce lien compare les différentes opérations des containers de la STL. Ca devrait t'aider à faire ton choix.

  7. #7
    Membre extrêmement actif
    Avatar de Ryu2000
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2008
    Messages
    9 827
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2008
    Messages : 9 827
    Points : 18 750
    Points
    18 750
    Par défaut
    Ok merci je vais regarder ça.

  8. #8
    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
    Points : 16 213
    Points
    16 213
    Par défaut
    Combien d'éléments va contenir ton conteneur ? Si la réponse est quelques centaines, pas plus, il y a des chances que vector soit plus rapide, même dans les opérations où sa complexité asymptotique est moins bonne.

    Ensuite, si tu as un compilateur pas trop vieux, que tu veux les perfs maximales sans avoir à gérer manuellement les désallocations, essaye de faire un vector<unique_ptr<mere>>. Si tu n'as pas accès à unique_ptr, je te conseille shared_ptr. Il y a certes une baisse possible des perfs, mais est-ce que tu l'as mesurée dans ton code ? Tu dis toi même que non.

  9. #9
    Membre extrêmement actif
    Avatar de Ryu2000
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2008
    Messages
    9 827
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2008
    Messages : 9 827
    Points : 18 750
    Points
    18 750
    Par défaut
    J'ai un vector avec au maximum 45 éléments.
    Un autre avec au maximum 48 éléments.

    Comme je l'ai dis, je remplis les vectors au début, puis je les vide petit à petit.

    Il y a d'autre vector qui se remplisse et se vide au cour du temps.
    Par exemple j'ai des vectors pour les tirs et les explosions.

    Au niveau des performances, je trouvais ça lent, mais c'est parce que j'avais un printf en boucle et c'est dingue comme les printf sont lent.
    C'est de l'OpenGL, et la scene n'arrête pas d'être reconstruite.

    Je n'ai pas vraiment pu faire un test efficace des performances réel entre pointeur et shared_ptr, mais comme le vector ne contenant que 45 objets la différence doit être vraiment faible.

    Si je n'ai qu'à faire un delete lorsque j'enlève un objet d'un vector, je n'ai pas besoin d'utiliser shared_ptr.

    Il y ni a qu'un vector qui a besoin de pointeur, à cause de l'héritage.

    Je pourrais utiliser des list, comme ça je gagnerai un peu sur les erase.
    Mais ça ne devrait pas faire une grosse différence.

    Et sinon entre un iterator et :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for(int i=0; i<monVecteur.size(); i++)
    La différence est-elle grande ?

  10. #10
    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
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par thierrybenji Voir le message
    Si je n'ai qu'à faire un delete lorsque j'enlève un objet d'un vector, je n'ai pas besoin d'utiliser shared_ptr.
    Il ne faut pas raisonner ainsi. Je suis presque certain que si je regardais ton code avec des delete, j'y trouverais des fuites mémoire (pas dans le cas nominal, probablement, mais dans les cas d'erreur). Alors, certes, pour un petit jeu comme ça, ce n'est pas très grave, mais c'est une bonne habitude à prendre que d'éviter ça. La raisonnement n'est pas : Je n'utilise les pointeurs intelligents que si j'en ai besoin, mais plus j'utilise les pointeurs intelligents sauf si vraiment je ne peux pas.
    Citation Envoyé par thierrybenji Voir le message
    Je pourrais utiliser des list, comme ça je gagnerai un peu sur les erase.
    Mais ça ne devrait pas faire une grosse différence.
    Tu ne gagnerais probablement rien, voire tu perdrais avec de si petits conteneurs. Un vecteur :
    - N'a aucun overhead mémoire par objet
    - Stocke toutes les données au même endroit, ce qui optimise l'utilisation du cache
    - Alloue de la mémoire d'un bloc, et non pas objet par objet
    Citation Envoyé par thierrybenji Voir le message
    Et sinon entre un iterator et :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for(int i=0; i<monVecteur.size(); i++)
    La différence est-elle grande ?
    Normalement aucune. L'écriture avec iterateur est un peu plus simple à porter avec d'autres conteneurs, si le besoin s'en fait sentir.

  11. #11
    Membre extrêmement actif
    Avatar de Ryu2000
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2008
    Messages
    9 827
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2008
    Messages : 9 827
    Points : 18 750
    Points
    18 750
    Par défaut
    Bon ben finalement je réutilise les shared_ptr et je garde les vectors.
    Ma solution de départ n'était pas trop mal finalement.

    Merci.

    Ça ne se voit pas mais maintenant j'ai des méthodes virtual et j'utilise des shared_ptr :
    http://youtu.be/XRQTX0sdE_0

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

Discussions similaires

  1. question à propos d'un std::vector encapsuler
    Par Date90 dans le forum C++
    Réponses: 2
    Dernier message: 05/04/2009, 15h20
  2. Question à propos des niveaux de transaction
    Par davy.g dans le forum Oracle
    Réponses: 3
    Dernier message: 18/01/2005, 15h31
  3. Petite question à propos du redbook...
    Par Michaël dans le forum OpenGL
    Réponses: 3
    Dernier message: 04/11/2004, 12h54
  4. Petite question à propos d'une requete
    Par ViBy dans le forum Langage SQL
    Réponses: 4
    Dernier message: 15/09/2004, 12h21
  5. Une question à propos des thread
    Par tscoops dans le forum C++Builder
    Réponses: 4
    Dernier message: 07/11/2003, 14h03

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