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 :

héritage à répétition et methodes virtuelles pures


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Mai 2002
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Mai 2002
    Messages : 55
    Par défaut héritage à répétition et methodes virtuelles pures
    j'aimerais bien faire un truc un peu special, que je decris dans ce petit bout de code. Oui oui je sais que deux instances de A sont créées dans la création de C, c'est bien ce que je veux

    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>
     
    using namespace std;
     
    class A {
    public:
      A() {
        cout << "A created" << endl;
      }
     
      virtual void method() = 0;
    };
     
    class B : public A {
    public:
      void method() {
        cout << "method B" << endl;
      }
    };
     
    class C : public B, public A {
    public:
      void method() { // la je veux redefinir A::method()
        cout << "method C" << endl;
      }
    };
     
    void func(A & a) {
      a.method();
    }
     
    int main() {
      C c;
      func(c);
    }

    mais le compilo il veut pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    inheritance.cpp:21: warning: direct base `A' inaccessible in `C' due to 
       ambiguity
    inheritance.cpp: In function `int main()':
    inheritance.cpp:34: error: `A' is an ambiguous base of `C'

    bon vous avez compris ce que je veux faire

    Vous me direz que ce n'est pas propre mais je ne vois pas le problème de conception moi, dans C il suffirait de spécifierA:: ou B::A:: pour avoir un accès non ambigus a tous les membres...
    qu'est ce que vous en dites ? comment résoudre ce "problème" ?

  2. #2
    jmv
    jmv est déconnecté
    Membre chevronné Avatar de jmv
    Profil pro
    Enseignant
    Inscrit en
    Mai 2004
    Messages
    395
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Mai 2004
    Messages : 395
    Par défaut
    C hérite de B et de A (héritage multiple, déconseillé) Est-ce nécessaire ?
    Je pense que ce que tu voulais est que :
    - B hérite de A,
    - C hérite de B (donc aussi de A)

    Ca marchera mieux avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class C : public B // et pas A
    { 
    public: 
      void method() { // la je veux redefinir A::method() 
        cout << "method C" << endl; 
      } 
    };

  3. #3
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2004
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2004
    Messages : 47
    Par défaut
    Dans ce cas n'oublie pas de déclarer "method" en virtual dans B

  4. #4
    Membre averti
    Inscrit en
    Mai 2002
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Mai 2002
    Messages : 55
    Par défaut
    oui... mais non. Je voulais bien que C herite de B (qui hérite de A) et d'une autre instance de A. De 2 instances de A quoi en quelque sorte. Mais attention C s'en fiche completement de B::A, tout ce qui l'interesse c'est un accès a B et un a A

    pourquoi ?
    prenons un exemple (pratique) :

    B hérite de Thread (comme en java)
    C hérite de Thread aussi

    ce sont 2 threads qui n'ont aucun rapport l'un avec l'autre. Pour autant, pourquoi C ne devrait pas hériter de B ?

    en Java cette solution est rendu possible (je crois) par les interfaces (Runnable en l'occurence) mais ya pas d'interface en C++ alors comment faire ?

  5. #5
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2004
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2004
    Messages : 47
    Par défaut
    Si tu hérites de B sans aucun but précis, autant ne pas le faire.

    En java l'utilisation d'interface te permet de définir des sortes de contrat, mais ne t'offres pas la possiblité de réutiliser du code.

  6. #6
    Membre averti
    Inscrit en
    Mai 2002
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Mai 2002
    Messages : 55
    Par défaut
    Si tu hérites de B sans aucun but précis, autant ne pas le faire
    au contraire, il est tout naturel dans ma conception objet que C herite de B
    mais si j'ai bien compris de toute facon j'ai pas le choix... enfin merci quant meme

  7. #7
    jmv
    jmv est déconnecté
    Membre chevronné Avatar de jmv
    Profil pro
    Enseignant
    Inscrit en
    Mai 2004
    Messages
    395
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Mai 2004
    Messages : 395
    Par défaut
    essaye ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class B : public virtual A {
    ...
    class C : public B, public virtual A {
    ...
    désolé je peux pas essayer chez moi, et l'héritage multiple n'est pas ma tasse de thé, d'ailleurs je ne suis toujours pas convaincu de la nécessité d'un héritage multiple ici.

    pour les interfaces: en C++ ce sont des classes qui ne contiennent que des méthodes virtuelles pures.

  8. #8
    jmv
    jmv est déconnecté
    Membre chevronné Avatar de jmv
    Profil pro
    Enseignant
    Inscrit en
    Mai 2004
    Messages
    395
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Mai 2004
    Messages : 395
    Par défaut
    Citation Envoyé par Nico65
    il est tout naturel dans ma conception objet que C herite de B
    si C hérite de B et que B est un thread, alors C est un thread, pas besoin d'héritage multiple (ou alors un truc m'échappe )

  9. #9
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2004
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2004
    Messages : 47
    Par défaut
    ou alors un truc m'échappe
    Pareil pour moi

  10. #10
    Membre averti
    Inscrit en
    Mai 2002
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Mai 2002
    Messages : 55
    Par défaut
    mais je veux que C soit un autre thread

    bon t'as peut-etre raison, C ne devrais peut-etre pas hériter de B...

  11. #11
    jmv
    jmv est déconnecté
    Membre chevronné Avatar de jmv
    Profil pro
    Enseignant
    Inscrit en
    Mai 2004
    Messages
    395
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Mai 2004
    Messages : 395
    Par défaut
    Citation Envoyé par Nico65
    mais je veux que C soit un autre thread
    mais évidemment que ce sera un autre thread. Les instances d'une classe sont indépendantes (enfin... normalement), seules les méthodes sont communes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    B b1, b2, b3; // 3 threads
    C c1, c2; // 2 autres threads
    Attention tout de même à déclarer virtuelle la méthode éxécuté par le thread (run() ou execute() ?)

    Citation Envoyé par Nico65
    bon t'as peut-etre raison, C ne devrais peut-etre pas hériter de B...
    non, je pense que C doit hériter uniquement de B.

  12. #12
    Membre averti
    Inscrit en
    Mai 2002
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Mai 2002
    Messages : 55
    Par défaut
    bon quelqu'un lui explique moi je fatigue...
    je veux que la creation de 1 C crée 2 thread (un pour C et un pour B)

    je retravaille sur mon modele avec B comme membre de C a la place

  13. #13
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Par défaut
    oui... mais non. Je voulais bien que C herite de B (qui hérite de A) et d'une autre instance de A. De 2 instances de A quoi en quelque sorte. Mais attention C s'en fiche completement de B::A, tout ce qui l'interesse c'est un accès a B et un a A
    Je vais surement dire une bêtise, mais selon ta conception j'aurais fait ceci:

    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
     
    class A {
     
      public:
        A() {
          cout << "A created" << endl;
        }
     
        virtual void method() = 0;
    };
     
    class B : public A {
     
      public:
        void method() {
          cout << "method B" << endl;
        }
    };
     
    class C : public A{
     
      public:
        void method() { // la je veux redefinir A::method()
          cout << "method C" << endl;
        }
        B* b;
    };

  14. #14
    jmv
    jmv est déconnecté
    Membre chevronné Avatar de jmv
    Profil pro
    Enseignant
    Inscrit en
    Mai 2004
    Messages
    395
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Mai 2004
    Messages : 395
    Par défaut
    Citation Envoyé par Nico65
    bon quelqu'un lui explique moi je fatigue...
    maisheuuuuu
    Citation Envoyé par Nico65
    je veux que la creation de 1 C crée 2 thread (un pour C et un pour B)
    là c'est clair (je savais bien qu'un truc m'échappait), dans ce cas c'est pas un héritage qu'il te faut, mais une composition. voir le post de moldavi.

  15. #15
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Par défaut
    Vous me direz que ce n'est pas propre mais je ne vois pas le problème de conception moi, dans C il suffirait de spécifierA:: ou B::A:: pour avoir un accès non ambigus a tous les membres...
    qu'est ce que vous en dites ? comment résoudre ce "problème" ?
    Pour toi c'est évident mais malheureusement le compilateur il ne réfléchit pas comme toi.

    En effet lorsque tu fais A:quelquechose) ou B:autrechose), tu n'as pas l'impression que c'est ambigû dans ta tête. Déjà réfléchis un peu à ce qu'il se passe lorsque tu utilises une référence sur une classe avec des héritages de partout (BEN c'est le bordel). Mais saches que pour compiler du code, il ne doit y avoir aucune ambiguité. On a pas encore inventé le compilo qui fait "Plouf-Plouf ça sera toi que je prendrais"...

  16. #16
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2003
    Messages : 65
    Par défaut
    Ce serait plus simple que ta classe C soit un A, mais qu'elle contienne un B.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class C : public A { 
    public: 
      B     b;
      void method() { // la je veux redefinir A::method() 
        cout << "method C" << endl; 
      } 
    };
    Je ne crois pas que Java te permettrait d'avoir deux méthodes identiques. C'est ce que tu obtiens en héritant à la fois de A et de B. Tu as deux fonctions method().

  17. #17
    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
    Par défaut Re: héritage à répétition et methodes virtuelles pures
    Citation Envoyé par Nico65
    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>
     
    using namespace std;
     
    class A {
    public:
      A() {
        cout << "A created" << endl;
      }
     
      virtual void method() = 0;
    };
     
    class B : public A {
    public:
      void method() {
        cout << "method B" << endl;
      }
    };
     
    class C : public B, public A {
    public:
      void method() { // la je veux redefinir A::method()
        cout << "method C" << endl;
      }
    };
     
    void func(A & a) {
      a.method();
    }
     
    int main() {
      C c;
      func(c);
    }
    Citation Envoyé par Je sais plus qui
    Tout problème de génie logiciel peut se résoudre à l'aide d'un niveau d'indirection supplémentaire
    Le seul moyen que je connaisse pour redéfinir une fonction virtuelle avec de l'héritage en diamant est de passer par une/des classe(s) intermédiaires :

    Quand tu veux écrire la classe C, tu peux écrire une classe C_From_B dérivant de B et redéfinissant A::méthode pour cette instance de A dans le C final, et une autre classe C_From_A dérivant drectement de A et faisant de même. Ta classe C dérive alors de C_From_B et de C_From_A.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  18. #18
    Membre expérimenté
    Profil pro
    Enculeur de mouches
    Inscrit en
    Septembre 2003
    Messages
    133
    Détails du profil
    Informations personnelles :
    Localisation : France, Creuse (Limousin)

    Informations professionnelles :
    Activité : Enculeur de mouches

    Informations forums :
    Inscription : Septembre 2003
    Messages : 133
    Par défaut
    Pour le problème de conception :
    -Est-ce que C doit créer un thread ?
    -Où doit il être un thread ?

    Pour pas me casser, j'aurais fait (mais pas sûr d'avoir tout compris, mais tant pis)

    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
     
    class Thread; // possède une "methode()" virtuelle pure.
     
    class ThreadA {
    ... methode() {...}... // on redéfinie la méthode pour A
    };
     
    class ThreadB {
    ... methode() {...}... // idem pour B
    };
     
    class QuiCreeDeuxThreadsQuelconques {
    ...
      Thread * t1;
      Thread * t2;
    ...
    }
     
    class UneAutrePourLeFun {
    ...
      ThreadA ta;
      ThreadB tb;
    ...
    };
    Là ça me paraît plus propre. Fin, ce que j'en dis, pour ce que j'ai compris au problème.

    Ce qui se conçoit bien s'exprime clairement, et les mots pour le dire viennent aisément
    NB : en passant sur ce qui a été dit au sujet du mot-clef vitrual. Ce me semble être des bêtises. Comment vouler vous redéfinir une méthode virtuelle, pure de surcroît, par une méthode classique, "statique" (au sens de "dont l'adresse pourra être résolue à la compilation", pas celui de "méthode de classe") ?
    Je ne dis pas que c'est un mauvaise chose de le préciser, au contraire, mais y'a pas de risque à l'oublier, je pense...

  19. #19
    Membre averti
    Inscrit en
    Mai 2002
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Mai 2002
    Messages : 55
    Par défaut
    bon alors SKZ81, toi tu as la palme, j'ai rien compris a ton code par rapport a mon probleme

    Pour le problème de conception :
    -Est-ce que C doit créer un thread ?
    -Où doit il être un thread ?
    je vais me faire tuer, mais j'ai bien du mal a voir la difference... quant tu cree un chien, tu cree un animal. Que le chien soit un animal, ca a une importance pour ton code mais surtout pour ton modele

    l'exemple des thread etait pas bon, alors admettons qu'une A contient une ressource partagee "x", protegee par un mutex. Les autres classes peuvent bloquer aussi ce mutex pour avoir un acces exclusif a "x". Deux choix (c'est un peu du peudo-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
    26
    27
    28
    29
    30
    31
    32
    33
     
    void func() {
       ...
       a.lock();
       X x = a.getX();
       ... // use x
       a.unlock();
    }
     
    class A1 {
       Mutex mutex;
       X x; 
     
       void uneMethodeQuelconqueQuiUtiliseX() {
          lock();
          ...
          unlock();
       }
     
       void lock() {mutex.lock();}
       void unlock() {mutex.unlock();}
    }
     
    class A2 : public Mutex {
       X x;
     
       void uneMethodeQuelconqueQuiUtiliseX() {
          lock();
          ...
          unlock();
       }
       X getX() {return x;}
    }
    enfin bref vous avez compris

  20. #20
    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
    Par défaut
    La deuxième méthode est mauvaise :

    On pourra passer à une fonction inf f(Mutex &) un objet du type A2, alors que ça n'a pas vraiment de sens.

    Si A2 hérite d'un Mutex, ça signifie en terme de conception qu'un objet de type A2 est un Mutex. Pour modèliser un lien de type A2 utilise un Mutex, tu as la composition, comme tu l'as marquée, ou dans des cas particuliers l'héritage privé.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

Discussions similaires

  1. Alternative au template de methode virtuelle pure
    Par lugarbleiz dans le forum Langage
    Réponses: 2
    Dernier message: 24/02/2010, 21h18
  2. Réponses: 4
    Dernier message: 09/10/2008, 09h04
  3. Réponses: 16
    Dernier message: 21/05/2007, 01h04
  4. Réponses: 9
    Dernier message: 13/02/2007, 15h29
  5. [debutant] probleme avec methode virtuelle pure
    Par Treuze dans le forum Débuter
    Réponses: 10
    Dernier message: 21/04/2006, 12h58

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