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 :

Problème pour enregistrer des instances de classes dérivées dans une liste


Sujet :

C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 15
    Par défaut Problème pour enregistrer des instances de classes dérivées dans une liste
    Bonjour,

    Je reprends le C++ (ESP8266 dans l'environnement Arduino) après ne l'avoir pas pratiquer pendant une décennie et je me retrouve confronter à un problème pour lequel je ne trouve pas de solution.
    Alors voilà, j'ai une classe A dont le constructeur est 'private' (pour ne pas pourvoir l'instancier) et une méthode est 'virtual' (qui sera appeler depuis une 'list' d'instance héritant de l'objet A).
    Comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class A
    {
      protected:
        A();
      public:
        virtual String method();
    };
    La classe B dérive de A :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class B : public A
    {
      public:
        B();
        String method();
    };
    La classe C dérive de A aussi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class C : public A
    {
      public:
        C();
        String method();
    };
    Trois instanciations des deux objets ainsi que la liste qui va stocker les instances.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    B inst0();
    B inst1();
    C inst2();
    std::list<A> liste;
    ET un bout de code pour appeler 'method' pour chaque instance stockée dans la 'list'.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int main(int argc, char ** argv)
    {
      String temp;
     
      for (std::list<A>::iterator it = liste.begin(); it != liste.end(); ++it)
      {
        temp += it->method();
      }
     
    }
    Cela fonctionne très bien.

    Maintenant, si j'ajoute dans le 'main' avant la boucle le code ci-dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    liste.push_back(inst0);
    liste.push_back(inst1);
    liste.push_back(inst2);
    Le compilateur me sort une erreur "no matching function for call to 'std::list<A>::push_back(B (&)())'".
    Ce qui se comprend mais comment on stocke différentes instances de classes dérivées dans une liste unique typée classe mère.

    Si quelqu'un peut m'éclairer voire m'aider à trouver une solution, cela serait formidable.

    D'avance merci

    Thoma

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Il faut un vecteur de pointeurs vers A, ou, à partir du C++11, un vecteur de std::ref<A>.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 15
    Par défaut
    Bonjour oodini,

    Effectivement, avec une liste de A * cela fonctionne. Merci.

    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
    #include <list>
     
    class A
    {
      protected:
        A();
      public:
        virtual String method();
    };
     
    class B : public A
    {
      public:
        B();
        String method();
    };
     
    class C : public A
    {
      public:
        C();
        String method();
    };
     
    A::A()
    {
    }
     
    B::B() : A()
    {
    }
     
    String B::method()
    {
      return "";
    }
     
    C::C() : A()
    {
    }
     
    String C::method()
    {
      return "";
    }
     
    int main(int argc, char ** argv)
    {
      String page;
      std::list<A *> liste_instances;
     
      B * inst0 = new B();
      B * inst1 = new B();
      C * inst2 = new C();
     
      liste_instances.push_back(inst0);
      liste_instances.push_back(inst1);
      liste_instances.push_back(inst2);
     
      for (std::list<A *>::iterator it = liste_instances.begin(); it != liste_instances.end(); ++it)
      {
        page += (*it)->method();
      }
     
      return 0;
    }
    Maintenant, où dois-je intégrer le std::ref<> de functional ?
    Je supposais placer le std:ref<A>() au niveau des 'push_back' mais sans résultat, j'obtiens un "undefined reference to `vtable for A'".

    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
    #include <functional>
    #include <list>
     
    class A
    {
      protected:
        A();
      public:
        virtual String method();
    };
     
    class B : public A
    {
      public:
        B();
        String method();
    };
     
    class C : public A
    {
      public:
        C();
        String method();
    };
     
    A::A()
    {
    }
     
    B::B() : A()
    {
    }
     
    String B::method()
    {
      return "";
    }
     
    C::C() : A()
    {
    }
     
    String C::method()
    {
      return "";
    }
     
    int main(int argc, char ** argv)
    {
      String page;
      B inst0();
      B inst1();
      C inst2();
      std::list<A> liste_instances;
     
      liste_instances.push_back(std:ref<A>(inst0));
      liste_instances.push_back(std:ref<A>(inst1));
      liste_instances.push_back(std:ref<A>(inst2));
     
      for (std::list<A>::iterator it = liste_instances.begin(); it != liste_instances.end(); ++it)
      {
        page += it->method();
      }
     
      return 0;
    }

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par Thoma HauC Voir le message
    Maintenant, où dois-je intégrer le std::ref<> de functional ?
    Je supposais placer le std:ref<A>() au niveau des 'push_back' mais sans résultat, j'obtiens un "undefined reference to `vtable for A'".
    C'est parce que ta méthode n'est pas définie pour A (si tu n'en pas besoin, déclare la en virtuelle pure).

    Ci-dessous figure une code fonctionnel.
    Je t'ai par ailleurs mis une autre manière d'itérer sur ton vecteur, de loin préférable à la première (dont le type de l'initialisateur devrait en outre être auto).

    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
    #include <functional>
    #include <iostream>
    #include <list>
    #include <string>
     
    using String = std::string;
     
    class A
    {
      protected:
        A() {};
      public:
        virtual String method() const { return "A"; }
    };
     
    class B : public A
    {
      public:
        B() {};
        virtual String method() const { return "B"; }
    };
     
    class C : public A
    {
      public:
        C() {};
        virtual String method() const { return "C"; }
    };
     
    int main()
    {
      String page;
     
      B inst0;
      B inst1;
      C inst2;
     
      std::list<std::reference_wrapper<A>> liste_instances;
     
      liste_instances.push_back(std::ref<A>(inst0));
      liste_instances.push_back(std::ref<A>(inst1));
      liste_instances.push_back(std::ref<A>(inst2));
     
      /*----------------------------------------------------------------------------------------------------------------*/
      for (std::list<std::reference_wrapper<A>>::const_iterator it = liste_instances.cbegin(); it != liste_instances.cend(); ++it)
    	page += it->get().method();
     
      std::cout << page << std::endl;
      page.clear();
     
      /*----------------------------------------------------------------------------------------------------------------*/
      for (const A& a: liste_instances)
    	page += a.method();
     
      std::cout << page << std::endl;
     
      return 0;
    }
    }
    Le deuxième for étant préférable au premier...

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 15
    Par défaut
    Bonjour oodini,

    Merci pour l'exemple, j'ai pu le transposer à mon cas.
    Non sans difficulté car certains points sont encore un peu flou.

    Thoma

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

Discussions similaires

  1. Réponses: 10
    Dernier message: 13/01/2008, 11h52
  2. Problème de vTable et Xcode
    Par OrthoMaker dans le forum Qt
    Réponses: 2
    Dernier message: 01/01/2008, 21h57
  3. Réponses: 8
    Dernier message: 16/10/2006, 12h28
  4. Problème d'installation oracle 8.1.7 sous NT
    Par Anonymous dans le forum Installation
    Réponses: 7
    Dernier message: 02/08/2002, 14h18
  5. Problème avec la mémoire virtuelle
    Par Anonymous dans le forum CORBA
    Réponses: 13
    Dernier message: 16/04/2002, 16h10

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