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 :

[C++] Template, héritage multiple et méthodes virtuelles


Sujet :

Langage C++

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 48
    Par défaut [C++] Template, héritage multiple et méthodes virtuelles
    Désolé pour le titre peu explicite mais je ne sais comment définir mon problème.
    J'ai fait un petit exemple qui synthétise un bout de conception
    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
     
    #include <iostream>
     
    template<class T>
    class ObjectManager
    {
    public:
      virtual void Manage()
      {
        std::cout << "Manage " << T::Str() << std::endl;
      }
    };
     
     
     class A : public ObjectManager<A>
    {
    public:
      static std::string Str(){return "A";}
    };
     
     
    class B : public A, public ObjectManager<B>
    {
    public:
      static std::string Str(){return "B";}
    };
     
     
    //Let's GO
     
    int main () 
    {
      A& a = *new B();
      a.Manage();
      return 0;
    }
    • J'ai une classe template "ObjectManager<T>" qui permet d'enregister mes objets dans des conteneurs
    • J'ai une classe A qui dérive de "ObjectManager<A>", l'héritage statique permet de faire ce qui est décrit dans le premier point.
    • Pour les besoins de ma conception j'ai des classes qui dérivent de A. Dans l'exemple c'est la classe B. Mais j'ai aussi besoin d'enregistrer les objets de type "B" alors je dérive aussi B de "ObjectManager<B>"


    Mon problème est décrit dans le main. Comment appeler à partir d'un objet de type dynamique B mais de type statique A, la méthode ObjectManager<B>::Manage() ?
    Et à l'inverse comment assurer que l'appel de ObjectManager<B>::Manage() va déclencher l'appel de ObjectManager<A>::Manage().

    Voila mon approche, peut-être aussi est-ce une erreur de conception, si vous avez des pistes...
    Merci !

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 48
    Par défaut
    [Edit]
    Une solution qui permet de faire ce que je veux, en rajoutant une méthode virtuel d'accés "CallObjectManager_Manage()" dans les classes A et B
    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
     
    #include <iostream>
     
     
    template<class T>
    class ObjectManager
    {
    public:
      virtual void CallObjectManager_Manage() = 0;
     
    protected:
      void Manage()
      {
        std::cout << "Manage " << T::Str() << std::endl;
      }
    };
     
     
      class A : public ObjectManager<A>
    {
    public:
      static std::string Str(){return "A";}
     
      virtual void CallObjectManager_Manage()
      {
        ObjectManager<A>::Manage();
      }
    };
     
     
    class B : public A, public ObjectManager<B>
    {
    public:
      static std::string Str(){return "B";}
     
      virtual void CallObjectManager_Manage()
      {
     
        ObjectManager<B>::Manage();
        A::CallObjectManager_Manage();
      }
    };
     
     
    //Let's GO
     
    int main () 
    {
      std::cout << "Test1" << std::endl;
      B* b = new B();
      b->CallObjectManager_Manage();
     
      std::cout << "Test2" << std::endl;
      A* a = b;
      a->CallObjectManager_Manage();
     
      return 0;
    }
    Le problème est que cette façon de faire est "intrusive" pour les classes A et B...

  3. #3
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Je n'ai pas réfléchie au problème de conception, tu pourrais détailler ta conception, surtout la partie qui permet d'enregistrer dans un conteneur ? Je ne vois pas l'interet d'héirter d'une classe pour faire ca.

    Pour ton problème, une solution pourrait être de faire une classe template spécifique qui a pour rôle d'hériter et de fournir les services de ObjectManager :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    template<class T, class U>
    class InheritanceObjectManager : public T, public ObjectManager<U>
    {
        virtual void Manage() { ObjectManager<U>::Manage(); }
    };
     
    class B : public InheritanceObjectManager<A, B> /*...*/

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 48
    Par défaut
    Bonjour,
    Merci de ta réponse, j'ai mis pas mal de temps à comprendre l'astuce...
    En tout cas je pense que cela résout le problème.

    Sinon du point de vue conception, j'ai choisi de dériver divers objet de la classe "ObjectManager<T>" pour permettre à leur construction et destruction de s'ajouter ou de se retirer de divers conteneurs. C'est une classe purement utilitaire.

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 48
    Par défaut
    Zut,
    Et si mes classes A et B n'ont pas de constructeurs par défaut, il faut spécialiser les constructeurs de InheritanceObjectManager<A, B> ?
    Si c'est le cas, cela devient compliqué...

  6. #6
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Tu peus jouer avec les templates variadic du prochain standard (ou des macros si tu veus pas te servir du C++01), et faire quelque chose comme :
    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
     
    template<class T>
    class ObjectManager
    {
    public:
      virtual void Manage()
      {
        std::cout << "Manage " << T::Str() << std::endl;
      }
      virtual ~ObjectManager(){}
    };
     
    template<class T, class U>
    class InheritanceObjectManager : public T, public ObjectManager<U>
    {
    public:
      template<class... Arg>
      InheritanceObjectManager(Arg... var):T(var...){}
      virtual void Manage() { ObjectManager<U>::Manage(); }
    };
     
     class A : public ObjectManager<A>
    {
    public:
      A(int){}
      static std::string Str(){return "A";}
    };
     
     
    class B : public InheritanceObjectManager<A, B>
    {
    public:
      B():InheritanceObjectManager(0) {}
      static std::string Str(){return "B";}
    };
    Les ... font partie de la syntaxe particulière des template variadics, lors de la définition d'un symbole ils indiquent une paquet de paramètre, lors de l'utilisation du symbole le fait de le dépaqueter. Je te laisse chercher sur internet pour les détails. (Un article sur le sujet sur le blog d'Emmanuel Deloget par exemple)

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 48
    Par défaut

    ça fonctionne nickel !
    Je vais me renseigner un peu plus en profondeur sur cette technique pour voir si je peux intégrer ça dans ma lib (au niveau du support des compilos).
    Merci beaucoup,
    @ bientôt,
    Damien.

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

Discussions similaires

  1. Héritage multiple et fonction virtuelle
    Par chronos dans le forum Langage
    Réponses: 5
    Dernier message: 17/02/2012, 10h15
  2. Héritage multiple et fonction virtuelle
    Par chronos dans le forum C++/CLI
    Réponses: 0
    Dernier message: 14/02/2012, 09h59
  3. [Héritage] Downcasting et méthodes virtuelles
    Par poukill dans le forum C++
    Réponses: 8
    Dernier message: 16/07/2007, 13h38
  4. Template, héritage multiple et redéfinition
    Par Paul Atreide dans le forum Langage
    Réponses: 5
    Dernier message: 31/10/2006, 14h00
  5. Exceptions, héritage et méthodes virtuelles
    Par Nuwanda dans le forum C++
    Réponses: 13
    Dernier message: 23/05/2006, 12h06

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