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 :

Redéfinition de méthode et principe de Liskov


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de Ekinoks
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2003
    Messages
    687
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2003
    Messages : 687
    Par défaut Redéfinition de méthode et principe de Liskov
    Salut !

    J'aurais quelque questions sur des problèmes de redéfinition de méthode en C++. Comme je n'ai pas réussi à trouver de solution (il en existe peu être pas), je vous soumet mes questions ^^;

    1> Il m'arrive fréquemment de vouloir empêcher la redéfinition d'une méthode pour les objet qui hérite de ma classe. Il me semble qu'en Java il existe le mot clé "final" pour faire ca... Es qu'il existe un équivalant en C++ ?

    2> Es qu'il existe un moyen de forcer l'exécution d'une méthode même si celle ci a était redéfinie et ce a partir de la classe mère ?
    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    struct A {
       virtual void f() {
          cout<<"code A"<<endl;
       }
    };
     
    struct B : public A {
       virtual void f() {
          A::f(); // Existe t'il un moyen de faire cette appelle automatiquement sans que la classe fille est a le faire ?
          cout<<"code A"<<endl;
       }
    };
    3> Existe t'il un moyen de redéfinir des méthodes templates dans une classe fille ?



    Merci pour votre aide.

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

    Informations professionnelles :
    Activité : aucun

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

    1- Si une méthode ne doit pas être redéfinie, il "suffit" de ne pas la déclarer comme virtuelle

    2- non, si tu veux qu'une méthode de la classe mère redéfinie dans la classe fille, il faut l'invoquer de manière explicite.

    Par contre, il est possible d'utiliser le concept de l'interface non virtuelle pour t'assurer que certaines parties soient effectuées de manière systématique:
    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
    class Base
    {
        public:
            void foo()
            {
                before();
                virtualCall();
                after();
            }
        protected:
            virtual void virtualCall()
            {
                /* partie virtuelle */
            }
        private:
            void before()
            {
                /* pré conditions */
            }
            void after()
            {
                /* post conditions */
            }
    };
    class Derivee : public Base
    {
        /*...*/
        protected:
            virtual void virtualCall()
            {
                /* comportement adapté à la classe dérivée */
            }
    };
    De cette manière, le comportement polymorphe se limite à ce qui est *réellement* à adapter au type dérivé

    3- non... une fonction template (ou une méthode de classe template) est adaptée au type utilisé au moment de la compilation

    Tu peux donc envisager une spécialisation partielle ou totale de la classe template de manière à adapter le fonctionnement au type réel, mais tu ne peux pas redéfinir cette fonction.

    Enfin, tu ne peux pas la redéfinir dans le sens polymorphe du terme, mais tu peux envisager de la redéfinir dans le sens d'un "recouvrement" de la fonction (la version dérivée de la fonction cachant la version de la classe de base).

    Cela implique que, si tu travaille sur des objets se faisant passer pour des instance de la classe de base, et que tu invoque la fonction, ce sera la version de la classe de base qui sera effectivement invoquée.
    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 éclairé Avatar de Ekinoks
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2003
    Messages
    687
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2003
    Messages : 687
    Par défaut
    Merci pour ta reponse koala


    Citation Envoyé par koala01 Voir le message
    1- Si une méthode ne doit pas être redéfinie, il "suffit" de ne pas la déclarer comme virtuelle
    Ha oui j'ai oublié de préciser, c'est dans le cas ou la méthode est déjà déclaré virtuelle dans un ancêtre... je cherche donc a arrêter la propagation du "virtual"


    Citation Envoyé par koala01 Voir le message
    2- non, si tu veux qu'une méthode de la classe mère redéfinie dans la classe fille, il faut l'invoquer de manière explicite.

    Par contre, il est possible d'utiliser le concept de l'interface non virtuelle pour t'assurer que certaines parties soient effectuées de manière systématique
    Ok, c'est bien cette méthode que j'utilise pour contourner le problème.
    Mais elle a quand meme le désavantage de devoir trouver des nom diffirent.
    Pour peu que cette astuce soit réaliser plusieurs foi sur un même méthode et on se retrouver avec une liste de nom : "Call", "virtualCall", "virtualCall2", "virtualCall3"...

    Mais bon, si c'est la seul solution, on va faire avec :p


    Citation Envoyé par koala01 Voir le message
    3-
    Erf, ok... c'est bien ce que je craignais :'(

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 633
    Par défaut
    Citation Envoyé par Ekinoks Voir le message
    Merci pour ta reponse koala



    Ha oui j'ai oublié de préciser, c'est dans le cas ou la méthode est déjà déclaré virtuelle dans un ancêtre... je cherche donc a arrêter la propagation du "virtual"
    Ce que tu peux faire, c'est partir sur une interface non virtuelle, comme indiqué plus haut, et la redéfinition de l'accessibilité de la méthode qui ne doit plus être réimplémentée de manière à la rendre privée

    De cette manière, la méthode virtuelle devient inaccessible au départ de "l'ensemble du code" lorsque l'on dispose de la classe dérivée, et n'est accessible que "depuis les méthodes de la classe" (de base ou dérivée) de manière générale.

    N'oublie pas que, bien qu'il soit possible de définir un nombre important d'héritage en cascade, il est généralement "cohérent" d'essayer de limiter les niveaux d'héritage à trois ou quatre (il y a eu une discussion sur le sujet il y a quelques mois... une recherche sur le forum devrait te permettre de la retrouver )

    Ok, c'est bien cette méthode que j'utilise pour contourner le problème.
    Mais elle a quand meme le désavantage de devoir trouver des nom diffirent.
    Pour peu que cette astuce soit réaliser plusieurs foi sur un même méthode et on se retrouver avec une liste de nom : "Call", "virtualCall", "virtualCall2", "virtualCall3"...
    En toute logique, tu ne devrais pas te retrouver face à la situation d'avoir plus de trois parties "distinctes" dans ta méthode de base:
    • une partie qui concerne la gestion des "pré conditions", une partie qui concerne la gestion des "post conditions" et une partie, potentiellement polymorphe, qui concerne la gestion particulière au type en cours d'utilisation qui se trouve entre les deux premières citées


    Si tu envisage une méthode doSomething(), par exemple, tu peux donc "facilement" décider que les différentes parties seront nommée
    doSomethingFirst() (ou doSomethingBefore() ou... n'importe quel terme indiquant le fait que cela survient... au début), doSomethingImpl, pour l'implémentation polymorphe de la fonction et doSomethingLast() (ou doSomethingAfter() ou... n'importe quel terme indiquant le fait que cela survient... à la fin)

    S'agissant de méthodes qui ne seront invoquées que dans une seule méthode, du moins pour deux des trois méthodes, le fait qu'elles se retrouvent avec des noms "à charnières et à rallonges" ne posera pas trop de problème

    N'oublie pas qu'ici, j'ai décidé qu'il y aurait des pré et des post conditions à vérifier, pour donner un exemple complet de ce qui peut se faire, mais que, dans la réalité des faits, il ne sera pas rare de n'avoir que des pré ou que des post conditions, ce qui limitera d'autant le nombre de "sous méthodes" pour lesquelles il faudra trouver un nom

    N'oublie pas non plus que, idéalement, le terme utilisé comme nom de fonction devrait représenter ne serait-ce que succintement le but poursuivi (ou le role joué) par cette fonction, raison pour laquelle je te conseille de simplement rajouter "before","impl"(émentation) ou "after" au nom de la fonction
    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 Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    une partie qui concerne la gestion des "pré conditions", une partie qui concerne la gestion des "post conditions" et une partie, potentiellement polymorphe, qui concerne la gestion particulière au type en cours d'utilisation qui se trouve entre les deux premières citées
    Le gros malheur de cette méthode, c'est qu'elle ne permet pas d'étendre les préconditions... (le require_else de eiffel)

    Un de mes gros griefs à C++, toujours pas adressé par C++0x.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 633
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    Le gros malheur de cette méthode, c'est qu'elle ne permet pas d'étendre les préconditions... (le require_else de eiffel)

    Un de mes gros griefs à C++, toujours pas adressé par C++0x.
    En toute logique, si tu as des pré (ou post) conditions valides pour une classe de base, elles doivent rester valides pour les classes dérivées (extension du principe de substitution).

    Si tu dois étendre ces conditions pour l'une des classes dérivées, tu reste tout à fait libre de les étendre dans le comportement polymorphe

    Je ne vois donc pas vraiment quel grief tu peux faire à ce sujet
    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. redéfinition de méthode
    Par greg08 dans le forum Langage
    Réponses: 8
    Dernier message: 28/10/2008, 14h59
  2. Réponses: 8
    Dernier message: 01/07/2008, 23h15
  3. héritage et redéfinition de méthodes
    Par Braillane dans le forum Langage
    Réponses: 4
    Dernier message: 07/01/2007, 18h47
  4. redéfinition de méthode et invocation
    Par magedo dans le forum Langage
    Réponses: 2
    Dernier message: 05/01/2007, 19h00
  5. [JPanel][LayoutManager] redéfinition de méthodes
    Par _KB_ dans le forum AWT/Swing
    Réponses: 4
    Dernier message: 06/06/2006, 14h22

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