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 :

Imiter le fonctionnement des constructeurs/destructeurs pour une méthode héritée (voir source)


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif Avatar de oxyde356
    Homme Profil pro
    Ingénieur Recherche Imagerie
    Inscrit en
    Février 2006
    Messages
    797
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur Recherche Imagerie

    Informations forums :
    Inscription : Février 2006
    Messages : 797
    Par défaut Imiter le fonctionnement des constructeurs/destructeurs pour une méthode héritée (voir source)
    Bonjour, j'aimerais savoir s'il était possible de créer une méthode fonctionnant un peu sur le principe d'un constructeur, c'est à dire que si la méthode appartient à une classe B dérivant de A, je voudrais que cette méthode appelle d'abord celle de A, comme un constructeur appelle d'abord le constructeur de la classe mère.

    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
    class A
    {
    	public :
     
    		virtual void init()
    		{
    			printf("A - init()\n");
    		}
    };
     
    class B : public A
    {
    	public :
     
    		virtual void init()
    		{ //doit appeler A::init() implicitement
    			printf("B - init()\n");
    		}
    };
     
    int main(int argc, char* argv[])
    {
    	B myB;
    	myB.init();
     
    	system("PAUSE");
     
    	return 0;
    }
    J'aimerais si possible ne pas avoir besoin de faire ce qui est en commentaire dans chaque méthode, comme pour le constructeur, j'aimerais que cela soit implicite, existe-t-il un mot clé C++, un pattern, une astuce :p pouvant faire cela ?

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Déjà, pourquoi voudrais tu initialiser ton objet autrement que par le constructeur

    RAII a vraiment de bons cotés

    Pour tout ce qui a trait aux autres méthodes, tu peux envisager l'idiome NVI (Non Virtual Interface)

    Cela prend une forme 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
    class Base
    {
        public:
            virtual ~Base(); // polymorphisme oblige
            void foo()
            {
                /* tout ce qui doit être effectué dans foo */
               doFoo(); // appel polymorphe de la partie spécifique au type réel
            }
        private:
            virtual void doFoo() = 0;
    };
    class Derivee : public Base
    {
        private:
            virtual void doFoo()
            {
                /* comportement spécifique pour Derivee */
            } 
    };
    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
    Membre très actif Avatar de oxyde356
    Homme Profil pro
    Ingénieur Recherche Imagerie
    Inscrit en
    Février 2006
    Messages
    797
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur Recherche Imagerie

    Informations forums :
    Inscription : Février 2006
    Messages : 797
    Par défaut
    Salut à toi et merci de répondre ^^
    Enfaite je me suis mal exprimé, je me sers de mon constructeur/destructeur mais j'aimerais que certaines méthodes puissent avoir ce comportement "d'aller regarder la fonction d'au dessus". Je me rend compte que j'aurais pas du minimiser mon exemple. Enfaite à la base j'avais mis 3 classes qui dérive comme suit :

    class A;
    class B : public A;
    class C : public B;

    Et je veux que quand j'utilise ma méthode myC.init() ça appelle TOUS les inits des classes du dessus comme un constructeur remonte par tous les constructeurs de ses classes mères. Au début j'avais aussi fais une technique init(), onInit() mais ça ne marche que si on se limite à 1 seule dérivation. Si on en fait 2 à la suite comme dans mon exemple ça ne marche plus :/

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Ta class B est elle une classe abstraite ou concrète

    Car il est possible de continuer sur le même style, mais il faut savoir si tu dois être en mesure de créer une instance de la classe "médiane" (B selon ton exemple) ou non...

    Ainsi, tu pourrais parfaitement envisager un code 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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    class A
    {
        public:
            void init()
            {
                /* comportement propre au type A */
                doInit(); /* appel du comportement spécifique au type réel */
            }
        private:
            virtual void doInit() = 0; /* !!! fonction virtuelle pure ==> 
                                        *classe abstraite 
                                        */
    };
    class B : public A
    {
        private:
            virtual void doInit()
            {
                /* comportement spécifique à B */
                subInit(); /* appel du comportement spécifique aux 
                            * types dérivés 
                            */
            }
            /* fonction à transformer éventuellement en virtuelle pure */
            virtual void subInit()
            {
                 /* ne fait sans doute rien */
            }
    };
    class C : public B
    {
        private:
            virtual void subInit()
            {
                /* comportement spécifique à C */
            }
    };
    class D : public B
    {
        private:
            virtual void subInit()
            {
                /* comportement spécifique à D */
            }
    };
    Ceci dit, je ne peux m'empêcher de rappeler que l'héritage est la relation la plus forte qui puisse exister entre deux classes et qu'il n'est cohérent de l'envisager que si l'on peut, effectivement, sémantiquement estimer que la classe dérivée EST UN objet du type de base particulier...

    Il ne faut pas oublier le principe de substitution de Liskov qui nous dit que, pour qu'il puisse y avoir héritage, toute propriété valide pour la classe de base se doit d'être valide pour la classe dérivée

    Je ne dis pas que tu es tombé dans le piège car je n'en sais pas assez sur tes classes A, B et C, mais il me semble opportun d'attirer ton attention sur ce fait et de t'inciter à réfléchir au fait qu'une agrégation peut s'avérer plus opportune (et l'est dans bien des cas )
    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
    Membre très actif Avatar de oxyde356
    Homme Profil pro
    Ingénieur Recherche Imagerie
    Inscrit en
    Février 2006
    Messages
    797
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur Recherche Imagerie

    Informations forums :
    Inscription : Février 2006
    Messages : 797
    Par défaut
    Nan t'inquiète pas je ne suis pas tombé dans ce piège là mais merci pour la leçon quand même. Et pour répondre à ta question avec l'information que j'aurais du donné dans mon précédent poste c'est que B est une classe concrète d'où mon problème enfaite (comment ça j'aurais du commencer par là ^^). Enfaite oui je l'ai pas dis car vu que je veux remonter de méthode en méthode c'était implicite que ces dites méthodes sont définies et pas virtuelles pures. Bref j'en suis venu au même point que toi, il faut faire un init1(), init2(), init3() ce qui n'est pas acceptable ou sinon faire une méthode init() et pas virtuel qui va apellé le Super::init() ( Super étant la classe mère dsl de le piquer au java pour l'exemple ) puis le onInit qui lui sera virtuel et définira l'initialisation de mon objet à proprement dit mais au final ça casse tout l'intérêt de faire séparer en deux méthodes je crois que je vais être obligé d'appeler la méthode du dessus manuellement ou de faire un changement au niveau de la conception de mon appli :/

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par oxyde356 Voir le message
    Nan t'inquiète pas je ne suis pas tombé dans ce piège là mais merci pour la leçon quand même. Et pour répondre à ta question avec l'information que j'aurais du donné dans mon précédent poste c'est que B est une classe concrète d'où mon problème enfaite (comment ça j'aurais du commencer par là ^^). Enfaite oui je l'ai pas dis car vu que je veux remonter de méthode en méthode c'était implicite que ces dites méthodes sont définies et pas virtuelles pures.
    La fonction que tu veux faire remonter, oui, pas forcément d'autres fonctions ou des morceaux du comportement à faire remonter...

    Complétons le diagramme, si tu le veux bien:
    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
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    /********************* classe de base **********************/
    class A
    {
        public:
            void foo() // NVI
            {
                /* partie propre à A */
                doFoo(); // invoquation de la partie spécifique à B, C ou D
            }
        private:
            virtual void doFoo() = 0;
    };
    /*************** premier niveau d'héritage ******************/
    class B : public A
    {
        private:
             /* B reste abstraite car doFoo n'est pas redéfinie... 
              * on ne peut pas instancier un objet de type B
              */
    };
    class C : public A
    {
        private:
            virtual void doFoo()
            {
                /* comportement spécifique à C */
                subFoo(); // invoquation des parties spécifiques aux types dérivés
            }
            virtual void subFoo()
            {
                /* ne fait rien, mais la définition de subFoo fait que C est 
                 * une classe concrète
                 */
            }
    };
    class D : public A
    {
        private:
            virtual void doFoo()
            {
                /* partie spécifique à D */
                subFoo();
            }
            virtual void subFoo() = 0; /* fonction virutelle pure... la classe est
                                       * abstraite... Mais pas à cause de doFoo
                                       */
    };
    /*************** deuxieme niveau d'héritage ******************/
    class E : public B
    {
        private:
            virtual doFoo() /* E devient une classe concrète */
            { 
                /* partie spécifique à E */
            }
    };
    class F : public C
    {
        private:
            /* ce n'est meme pas obligatoire, vu que C est une classe concrète
             * mais il y a peut être "quelque chose de plus" à faire pour F
             */
            virtual void subFoo()
            {
                /* partie spécifique à F */
            }
    };
    class G : public D
    {
        private:
            /* subFoo n'est toujours pas redéfinie... G est une classe abstraite
             * ...peut être au prochain niveau d'héritage ?
             */
    };
    class H : public D
    {
        private:
            virtual void subFoo()
            {
                /* partie spécifique à H */
            }
    };
    Comme tu peux le remarquer, il n'y a strictement aucune obligation au fait que seule la classe "ancêtre" soit abstraite
    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

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

Discussions similaires

  1. Ajouter des variables supplémentaires pour une acp
    Par fafabzh6 dans le forum SAS STAT
    Réponses: 7
    Dernier message: 31/01/2008, 16h31
  2. Des Boutton Flash pour une page php
    Par Iori Yagami dans le forum Flash
    Réponses: 5
    Dernier message: 14/10/2007, 21h29
  3. [W3C] Créer des liens chapitres pour une vidéo
    Par Xann_71 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 1
    Dernier message: 27/08/2007, 13h21
  4. Où trouver des images PNG pour une application ?
    Par Pythonesque dans le forum Imagerie
    Réponses: 5
    Dernier message: 10/07/2007, 14h44
  5. [Interbase] Liste des utilisateurs enregistrés pour une BD
    Par touhami dans le forum Bases de données
    Réponses: 4
    Dernier message: 14/02/2007, 07h29

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