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 sur 2 classes CDialog?


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Inscrit en
    Novembre 2002
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 55
    Points : 32
    Points
    32
    Par défaut Héritage sur 2 classes CDialog?
    Bonjour,
    je dispose de 2 classes héritant de CDialog. Elles sont pratiquement identiques sauf leur boîte de dialogue. Peut-on faire un héritage intermédiaire? Sinon, quelle meilleure architecture à adopter?
    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
     
    class CMyDial : public CDialog
    {
      enum { IDD = IDD_MyDial};
      void set();
      void setTracker();
      void setDisplay();
    {{AFX_VIRTUAL(CMyDial )
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    	virtual BOOL OnInitDialog();
    	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    	afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
    	afx_msg void OnPaint();
    	afx_msg void OnSize(UINT nType, int cx, int cy);
    	afx_msg void OnMove(int x, int y);*/
    	//}}AFX_VIRTUAL
    }
     
    class CMyDial1 : public CDialog
    {
      enum { IDD = IDD_MyDial1};
      void set();
      void setTracker();
      void setDisplay();
     
    {{AFX_VIRTUAL(CMyDial )
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    	virtual BOOL OnInitDialog();
    	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    	afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
    	afx_msg void OnPaint();
    	afx_msg void OnSize(UINT nType, int cx, int cy);
    	afx_msg void OnMove(int x, int y);*/
    	//}}AFX_VIRTUAL
    }

    Merci

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Le fait est que, lorsque deux classes ont une même classe de base et qu'une quatirème classe doit hériter des deux première, tu te trouve dans une situation que l'on appelle "l'héritage en diamant" (en fait, ici, c'est plutot en losange ):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
           Base
          /    \
         /      \
     Derivee1 Derivee2
         \      /
          \    /
         Derivee3
    et que cette situation est rarement intéressante du fait des conflits qu'elle risque d'engendrer (quand on veut travailler sur Base, on travaille avec Derivee1::Base ou avec Derivee2::Base... ou doit-ce être la même base ) ou du fait de la nécessité de déclarer l'héritage de de Derivee1 et de Derivee2 vis à vis de Base virtuel, ce qui apporte également son lot de problèmes.

    Si donc, l'idée que tu as en tête est de créer une troisième boite de dialogue qui contient simplement les deux autres, le mieux est, sans doute, de:
    1. Faire en sorte que les classes que tu as appelé CMyDial et CMyDial1 soient en réalité considérés comme... des composant de ta boite de dialogue
    2. Créer des boites de dialogue permettant d'utiliser ces deux composants personnalisés de manière autonome
    3. Créer une boite de dialogue contenant les deux composant personnalisés, placés selon ton gout
    Mais nous partons alors sur une aggrégation, et non plus sur un héritage (hormis l'hértiage unique de la troisième boite de dialogue qui hérite directement de CDialogue et non plus de CMyDial ni de CMyDial1)
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Nouveau membre du Club
    Inscrit en
    Novembre 2002
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 55
    Points : 32
    Points
    32
    Par défaut
    L'idée était plutôt de faire cela...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
            CDialog
                |   
                |    
           CMyDialType 
             /      \
            /        \
    CMyDial1  CMyDial2
    Mais la ressource crée dans CtypeDial ne sert donc à rien... Toutes les fonctions sont définies dans CMyDialType. Seules résident dans les classes CMyDialx constructeur, destructeur, et déclaration de l'ID de ma dialog. Ca passe cela?

    Merci

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Ouppsss... Au temps pour moi...

    Mais, sur base de l'explication et du code fourni, je me suis quelque peu fourvoyé

    Il n'y a, a priori, aucune restriction quant au fait de faire dériver une classe d'une autre qui, elle-même, dérive d'une troisième classe que nous pouvons considérer comme ancêtre.

    Et cela peut même, d'après la norme, aller encore beaucoup plus loin car la norme préconise, pour les compilateurs qui la respectent, de supporter au minimum 1024 classe de base directes et 16384 classes de bases directe et indirectes pour une seule classe...

    Tu vois donc qu'il est tout à fait possible de donner libre cours à ta folie de l'héritage (d'autant plus qu'il s'agit ici... de minimum, et que ton compilateur peut en supporter d'avantage )

    Mais, si j'ai écris "a priori" au début de ma réponse, ce n'est pas anodin, car il y a d'autres paramètres à prendre en compte avant de décider de le faire...

    de manière non exhaustive, nous pouvons citer:
    • Que t'apporterait le fait de faire dériver une classe "générique" de CDialog et de faire dériver tes classes utiles de cette classe En d'autre termes, pourquoi ne pas faire, directement dériver boites de dialogue de... CDialog
    • Le fait d'avoir une hiérarchie d'héritage trop "profonde" a tendance à rendre les choses vraiment complexes, tant à l'utilisation (puis-je utiliser un pointeur Mere1 dans mon cas ou dois-je utiliser un pointeur ArriereArriereArrriereGrandMere, pour être sur que la conversion soit envisageable, et, surtout, pour avoir accès aux comportements qui m'intéressent )
    • D'aucun estiment (avec raison) qu'au delà de trois niveau d'héritage, cela devient réellement du superflu
    • La bibliothèque IHM que tu utilise (vu que c'est la situation que tu dépeint) accepte-t-elle que l'on fasse hériter une classe d'une autre classe qui, elle-même, hérite d'une classe de cette biblitohèque
    • et j'en oublie surement
    Tout cela pour dire que, oui, tu peux le faire, mais... il y a un grand MAIS à prendre en compte avant de te donner une réponse définitive

    Et, je ne dispose pas actuellement des informations qui me permettent d'évaluer sereinement les implications de ce MAIS
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Nouveau membre du Club
    Inscrit en
    Novembre 2002
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 55
    Points : 32
    Points
    32
    Par défaut
    Merci Koala

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Que t'apporterait le fait de faire dériver une classe "générique" de CDialog et de faire dériver tes classes utiles de cette classe  En d'autre termes, pourquoi ne pas faire, directement dériver boites de dialogue de... CDialog
    Je reviens au fait que l'idée est que ce qui diffère mes classes filles l'une de l'autre est simplement la ressource graphique... les fonctionnalités sont les mêmes. Donc dériver mes filles de CDialog reviendrait à pratiquemenht faire du copier coller de l'une par rapport à l'autre, avec ce qui diffère la ressource graphique. Je veux donc passer par une classe intérmédiaire pour factoriser cela.

    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
     
    class CMyDialType : public CDialog
    {
      enum { IDD = IDD_MyDialType};
      void set();
      void setTracker();
      void setDisplay();
    {{AFX_VIRTUAL(CMyDial )
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    	virtual BOOL OnInitDialog();
    	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    	afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
    	afx_msg void OnPaint();
    	afx_msg void OnSize(UINT nType, int cx, int cy);
    	afx_msg void OnMove(int x, int y);*/
    	//}}AFX_VIRTUAL
    }
     
    class CMyDial1 : public CMyDialType 
    {
      enum { IDD = IDD_MyDial1};
     CMyDial1();
     ~CMyDial1();
     
    }
     
    class CMyDial2 : public CMyDialType 
    {
      enum { IDD = IDD_MyDial2};
     CMyDial2();
     ~CMyDial2();
     
    }
     
    void main()
    {
    CMyDial2 *mydial2 = new  CMyDial2(); 
    mydial2->setTracker();
     
    CMyDial1 *mydial1 = new  CMyDial1(); 
    mydial1->setTracker();
     
     
     
    }
    Ce code a t'il du sens?

    Ou alors on opte pour une solution plus simple maos lourde, ie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
            CDialog
             /      \
            /        \
    CMyDial1  CMyDial2

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Mais, alors, ne pourrait on pas envisager le fait que la ressource graphique n'est en réalité que... du détail d'implémentation, qui pourrait parfaitement être géré dans une classe unique, en fonction d'un argument supplémentaire fournit au constructeur

    Je m'explique...

    tu va te trouver face à la situation (je laisse volontairement l'héritage sur le coté) proche de
    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
    class MyDial1
    {
        publilc:
            MyDial1():someStuff(new SomeStuff)
            {
            }
        private:
             SomeStuff* stuff;
    };
    class MyDial2
    {
        public:
            MyDial1():stuff(new OtherStuff)
            {
            }
        private:
            OtherStuff * stuff;
    };
    Dés lors, étant donné que SomeStuff et OtherStuff ont des comportements, finalement, fort similaire, pourquoi ne pas envisager que ces deux classe aient des comportement polymorphes, grace à un héritage commun
    Cela te donnerait un résultat proche de
    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
    class BaseStuff /* : public CElement */
    {
        public:
            BaseStuff(/*...*/){}
            virtual ~BaseStuff();
    };
    class SomeStuff : public BaseStuff
    {
    };
    class OtherStuff : public BaseStuff
    {
    };
    /* enum eStuffType
    {
        stSome,
        stOther
    };
    */
    class MyDial : public CDialog
    {
        public:
            MyDial(eStuffType s): stuff(s==stSome? new SomeStuff : new OtherStuff){}
        private:
            BaseStuff * stuff;
     
    };
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Réponses: 4
    Dernier message: 27/09/2012, 17h37
  2. Pointeur sur ma classe issue de CDialog
    Par Nixeus dans le forum Langage
    Réponses: 8
    Dernier message: 16/03/2010, 13h44
  3. [Conception] Héritage sur Plusieurs classes abstraites
    Par facilus68 dans le forum Langage
    Réponses: 9
    Dernier message: 20/03/2009, 13h06
  4. pb héritage sur classe abstraite et iterator
    Par black-falco dans le forum C++
    Réponses: 21
    Dernier message: 05/01/2008, 16h38
  5. Réponses: 19
    Dernier message: 05/06/2007, 08h13

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