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 :

[conception] variations sur le pattern "Template Method"


Sujet :

C++

  1. #1
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut [conception] variations sur le pattern "Template Method"
    Bonjour à tous,

    sur vos conseils, je suis parti sur l'implémentation d'un ensemble de classes en utilisant le Template Method. Ca donne à peu près 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
    class Mere
    {
    [...]
    void  MethodImpl();
    virtual void MethodDerivate() = 0;
    };
     
    class Fille1 : public Mere
    {
    void MethodDerivate(){<mon code ici>}
    };
     
    class Fille2 : public Mere
    {
    void MethodDerivate(){<mon code (différent) ici>}
    };
    Cela fonctionait très bien. Mais voilà qu'aujourd'hui, je dois apporter une modification. En effet, la classe Fille2 va maintenant devoir gérer des données propres à elle que Fille1 n'aura pas. Prenons un tableau de int pour l'exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class Fille2 : public Mere
    {
    void MethodDerivate(){<mon code (différent) ici>}
    vector<int> m_array;
    };
    Jusque là, tout va bien. Je voudrais maintenant une méthode qui modifie ce tableau, qui le vide par exemple. Donc j'ai fait 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
    class Mere
    {
    [...]
    void  MethodImpl();
    virtual void MethodDerivate() = 0;
    virtual void ClearArray() = 0;
    };
     
    class Fille1 : public Mere
    {
    void MethodDerivate(){<mon code ici>}
    void ClearArray(){m_array.clear();}
    vector<int> m_array;
    };
     
    class Fille2 : public Mere
    {
    void MethodDerivate(){<mon code (différent) ici>}
    void ClearArray(){}
    };
    Jusqu'ici tout va bien. Le problème c'est que maintenant, je voudrais appeler ClearArray depuis une méthode implémentée dans la classe Mere, ce qui nous donnerais quelque chose comme 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
    class Mere
    {
    [...]
    void  MethodImpl(ClearArray()); //modif ici
    virtual void MethodDerivate() = 0;
    virtual void ClearArray() = 0;
    };
    
    class Fille1 : public Mere
    {
    void MethodDerivate(){<mon code ici>}
    void ClearArray(){m_array.clear();}
    vector<int> m_array;
    };
    
    class Fille2 : public Mere
    {
    void MethodDerivate(){<mon code (différent) ici>}
    void ClearArray(){}
    };
    Mais là, ça ne fonctionne pas. Ca plante à l'exécution:
    R6025: pure virtual call.
    J'espère avoir été clair, et si vous m'avez suivi, je serais bien aise de recevoir vos conseils avisés

    merci.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  2. #2
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Normalement, ça devrat marcher.
    Mais les "()" à la place des "{}", c'est une erreur de recopie ou pas ?

  3. #3
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Euh, lesquels?
    J'ai bien peur que ce ne soit pas une erreur de copier/coller, mais une erreur "tout court"
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  4. #4
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Là où tu as indiqué que tu avais modifié le code de la classe mère.

  5. #5
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Oui en effet, c'était une erreur. Et tu as raison, cela fonctionne, j'ai fait un test ce matin. Mon erreur est donc ailleurs.

    pour ton aide
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  6. #6
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    pour info, et on ne sait jamais, quelqu'un pourra s'intéresser au problème un jour, je poste le code que j'ai testé ce matin et qui fonctionne parfaitement:
    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
    /// fichier.h
    #pragma once
    #include <vector>
     
    class CMere 
    {
    public:
        virtual ~CMere();
     
        virtual void f1() = 0;
        virtual void f2() = 0;
        void f3();
     
    protected:
        std::vector<int> m_vector1;
    };
     
     
    class CFille1 : public CMere
    {
    public:
        CFille1();
        ~CFille1();
     
        void f1();
        void f2();
     
    private:
    };
     
     
    class CFille2 : public CMere
    {
    public:
        CFille2();
        ~CFille2();
     
        void f1();
        void f2();
     
    private:
        std::vector<int> m_vector2;
    };
    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
    ///fichier .cpp
    #include "stdafx.h"
    #include "fichier.h"
     
    //////////////////////////////////////////////////////////////////////////
    CMere::~CMere()
    {
        m_vector1.clear();
    }
     
     
    void CMere::f3()
    {
        f2();
    }
     
    //////////////////////////////////////////////////////////////////////////
     
    CFille1::CFille1(){}
     
    CFille1::~CFille1(){}
     
    void CFille1::f1()
    {
        m_vector1.push_back(2);
    }
     
    void CFille1::f2(){}
     
    //////////////////////////////////////////////////////////////////////////
     
    CFille2::CFille2(){}
     
    CFille2::~CFille2()
    {
        m_vector2.clear();
    }
     
    void CFille2::f1()
    {
        m_vector1.push_back(2);
        m_vector2.push_back(3);
    }
     
    void CFille2::f2()
    {
        m_vector2.push_back(4);
    }
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  7. #7
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Pour info: en fait, mon erreur venait que fait que j'apellais ma fonction (f2() dans l'exemple ci-dessus) dans le destructeur de la classe mere.
    Je ne comprend pas trop pourquoi...
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    731
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 731
    Points : 574
    Points
    574
    Par défaut
    Citation Envoyé par r0d
    Pour info: en fait, mon erreur venait que fait que j'apellais ma fonction (f2() dans l'exemple ci-dessus) dans le destructeur de la classe mere.
    Je ne comprend pas trop pourquoi...
    Dans ta classe mère, f2 était une fonction virtuelle pure et implémentée uniquement par les classes dérivées, c'était donc normal d'avoir ce type de message.

  9. #9
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par ep31
    Dans ta classe mère, f2 était une fonction virtuelle pure et implémentée uniquement par les classes dérivées, c'était donc normal d'avoir ce type de message.
    Oui mais pourquoi ai-je le droit de l'appeler dans les autres méthodes de ma classe mère, mais pas dans le destructeur?
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    731
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 731
    Points : 574
    Points
    574
    Par défaut
    Citation Envoyé par r0d
    Oui mais pourquoi ai-je le droit de l'appeler dans les autres méthodes de ma classe mère, mais pas dans le destructeur?
    Si tu es dans une méthode quelconque (hors destructeur) de ta classe mère, la fonction f2() appelée sera celle de la classe dérivée. Par contre, dans le cadre de l'appel au destructeur de la classe mère, le destructeur de la classe dérivée est exécuté en premier, ce qui fait donc que l'objet this de la classe dérivée n'existe plus. Dans ce cadre-là, le destructeur de la classe mère n'aurait plus d'autre choix que d'exécuter le fonction f2 virtuelle pure.

  11. #11
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Dans le constructeur et le destructeur de la classe mère, la seule chose qui existe est la classe mère.
    Au début, à l'instanciation, la classe mère est crée, son constructeur est appelé. Le type de la classe est à ce moment celui de la classe mère.
    Ensuite seulement le constructeur fils est appelé et l'objet devient du bon type.
    Pour le destructeur, c'est exactement l'inverse.

    -> il est très vivement déconseillé de faire appel à des fonctions virtuelles dans les constructeurs et les destructeurs. Ce livre http://c.developpez.com/livres/#L2744071447 donne des infos plus détaillées sur d'autres déconseils/interdits de ce type.
    D'ailleurs dans ton cas, ta fonction virtuelle est en fait à appeler dans le destructeur de la classe fille et non dans le destructeur de a classe mère puisque l'objet à effacer est déjà détruit à ce moment.

  12. #12
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Ok, c'est clair maintenant!
    Vraiment

    P.S: l'exemple que j'ai donné n'avait aucun sens, c'était juste pour comprendre la problématique.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 28/04/2011, 09h58
  2. Réponses: 2
    Dernier message: 26/12/2010, 22h08
  3. patron de méthode (Template method pattern)
    Par gilloull dans le forum Design Patterns
    Réponses: 6
    Dernier message: 20/10/2009, 17h26
  4. [Template] methode template d'une classe pas template
    Par bigquick dans le forum Langage
    Réponses: 8
    Dernier message: 25/03/2005, 15h09

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