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 :

quelle est la portée de la surcharge ?


Sujet :

C++

  1. #1
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut quelle est la portée de la surcharge ?
    Bonjour,

    effectivement, je me pose la question de connaitre la portée de la surcharge. De par mon expérience, j'ai l'impression que la surcharge de fonctions (des fonctions portant le même nom mais ayant des signatures différentes) ne peut se faire qu'au sein d'une même classe et pas au sein de deux classes ayant une relation mère/fille.

    Le cas concret qui me pose problème et où j'aimerai bien que la portée soit "héréditaire" en quelque sorte, est le suivant:
    Je défini une fonction template dans une classe mère, utilisée par plusieurs classes filles, avec des types spécifiques. Chacune de ces classes filles utilisent la fonction template, qui fait appel à des fonctions spécialisées, ayant des paramètres différents, mais portant le même nom; d'où la notion de surcharge. Mais, cela ne fonctionne pas.

    Concrètement :

    Soit une classe "AbstractClient", classe mère qui implémente la fonction template.
    Une autre classe, gère une collection de classes filles de AbstractClient sous forme de pointeur AbstractClient*, et appelle les fonctions virtuelles "processFrame" avec des objets de classes filles de Frame, sous la forme de Frame* :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    class AbstractClient
    {
       template < typename FrameSpe > void checkFrame&#40; Frame* pFrame&#41;
       &#123;
          FrameSpe* pFrameSpe = dynamic_cast<FrameSpe*>&#40;pFrame&#41;;
          if &#40; pFrameSpe &#41; 
             processFrame&#40; pFrameSpe &#41;;
       &#125;
       virtual void processFrame&#40; Frame* &#41;
       &#123; 
          TRACE&#40;"Ce type de Frame n'est pas géré ! "&#41;;
       &#125;
    &#125;;
    et une des classe fille de AbstractClient :

    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
     
    class ConcreteClient
    &#123;
       void processFrame&#40; Frame* pFrame &#41;
       &#123;
          checkFrame<FrameToto>&#40;pFrame&#41;;
          checkFrame<FrameTata>&#40;pFrame&#41;;
          checkFrame<FrameTiti>&#40;pFrame&#41;;
       &#125;
     
       // fonction qui traite les FrameToto
       void processFrame&#40; FrameToto* pFrame&#41;
       &#123; // faire quelque chose avec des FrameToto &#125;
     
       // fonction qui traite les FrameTata
       void processFrame&#40; FrameTata* pFrame&#41;
       &#123; // faire quelque chose avec des FrameTata &#125;
     
    &#125;;

    Cette structure de classes me permettrait de gérer un grand nombre de classes héritant de Frame (j'en ai 46 dans le monde concret, selon un arbre d'héritage de à 3 niveaux), et un nombre de classes clientes variables (au moins une vingtaine), héritant de "AbstractClient".

    Mais ce code ne marche pas, tel quel : les fonctions "spécialisées pour les sous-types de Frame" ne sont jamais appelées.
    Par contre, si je mets la fonction template dans ConcreteClient, la ça fonctionne.
    D'où mon impression de départ : "la portée de la surcharge de fonction semble n'être possible qu'au sein d'une même classe, et ne peut s'hériter".
    Et c'est bien dommage !
    Je ne sais pas si j'ai été très clair. L'avis des experts m'intérresse...

    La seule solution que je vois est de ne pas utiliser de fonction template, mais de coder le "dynamic_cast" dans chaque processFrame(Frame*) des classes héritant de AbstractClient.

  2. #2
    Rédacteur
    Avatar de bigboomshakala
    Homme Profil pro
    Consultant Web .NET
    Inscrit en
    Avril 2004
    Messages
    2 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Consultant Web .NET
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2004
    Messages : 2 077
    Points : 2 757
    Points
    2 757
    Par défaut
    salut,

    hmm tout n'est pas clair dans ma tête. Et le fait que la classe mère est une méthode checkFrame qui fait appelle à processFrame et que la classe fille est des méthodes processFrame appelant checkFrame me perturbe un peu.

    Si je ne suis pas trop à côté de la plaque, ce que tu essaies d'appliquer c'est le pattern "Patron de méthodes" (cf. template method).

    Pour résumé, la classe mère abstraite définit une méthode patronMethode() appelant une ou plusieurs méthodes primitiveX() virtuelles pures (et généralement privées). A la charge des classes filles d'implémenter les méthodes primitivesX().

    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
    classe mere
    &#123;
    public&#58;
       void patronMethode&#40;&#41;
       &#123;
          ...
          primitive1&#40;&#41;;
          ...
       &#125;
    ...
     
    protected&#58;
       void primitive1&#40;&#41; = 0;
    &#125;;
     
    classe fille1 &#58; public mere
    &#123;
    ...
    private&#58;
       void primitive1&#40;&#41;
       &#123;
          // implémentation fille1
       &#125;
    &#125;;
     
    classe fille2 &#58; public mere
    &#123;
    ...
    private&#58;
       void primitive1&#40;&#41;
       &#123;
          // implémentation fille2
       &#125;
    &#125;;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    fille1 f1;
    fille2 f2;
     
    f1.patronMethode&#40;&#41;;
    f2.patronMethode&#40;&#41;;
    A adapter à ton cas.

  3. #3
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    La surcharge dans une hiérarchie se traduit par un masquage.
    => using devrait être ton ami -- je ne l'ai jamais essayé avec des templates au milieu.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  4. #4
    Membre à l'essai
    Inscrit en
    Août 2005
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 21
    Points : 19
    Points
    19
    Par défaut
    juste un idee

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void processFrame&#40; Frame* pFrame &#41; 
    &#123; 
    AbstractClient &#58;&#58;checkFrame<FrameToto>&#40;pFrame&#41;; 
    AbstractClient &#58;&#58;checkFrame<FrameTata>&#40;pFrame&#41;; 
    AbstractClient &#58;&#58;checkFrame<FrameTiti>&#40;pFrame&#41;; 
    &#125;

  5. #5
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut
    bigboomshakala : sur le principe, c'est ça, à part qu'il faut y ajouter des signatures différentes pour les fonctions (pour les spécialiser dans le traitement de classes spécialisées), le tout saupoudrer de template...

    Luc Hermitte : 'La surcharge dans une hiérarchie se traduit par un masquage', qu'est-ce que tu veux dire par là ? je vais essayer de me pencher sur le "using" directive...

    lepoutho : merci de ta proposition, mais mon problème apparaît dans l'autre sens : il monte de ConcretClient vers AbstractClient, c'est à la descente que ça foire...

    Mais je ne vais pas non plus implémenter une usine à gaz, parce que le principe c'est justement de simplifier le bazar et d'avoir des ConcretClient qui puissent dire dans leur processFrame(Frame*) générique :
    "alors moi, ce qui m'interresse c'est les FrameToto, FrameTata, FrameTiti, le reste je m'en cogne".
    et puis charge à elles d'implémenter les fonctions spécialisées de traitement : processFrame( FrameToto*), processFrame(FrameTata*), processFrame(FrameTiti*),

    Au pire, j'implémente mon template par une macro, et le tour est joué, mais, quelque part ça me chiffonne d'utiliser les macros.
    Point de vue personnelle, pas de polémique.

    Merci pour votre aide en tout cas !

  6. #6
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Ca veut dire que par défaut (sans using), dans les enfants on ne surcharge (ajout) pas, mais on masque (RAZ puis ajout).
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    54
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2004
    Messages : 54
    Points : 76
    Points
    76
    Par défaut
    Moi, j'ai l'impression que les choses se passent de la façon suivante:
    dans ta fonction template, tu appelles processFrame sur un descendant de Frame*. La seule fonction trouvée qui correspond est celle de la classe
    AbstractClient. Comme celle-ci est virtuelle, le programme recherche une fonction processFrame ayant la même signature dans la classe fille et n'appelle donc pas les surcharges de ta fonction.
    Si tu mets la fonction template dans les classes filles, celle-ci trouvent automatiquement la bonne fonction, et donc pas de prob.
    Ma solution (a tester): changer l'appel à processFrame dans la fonction template en this->processFrame. De cette façon, l'appel prendra en compte les surcharges présentes dans la classe fille.

    Citation Envoyé par Luc Hermitte
    Ca veut dire que par défaut (sans using), dans les enfants on ne surcharge (ajout) pas, mais on masque (RAZ puis ajout).
    Tu peux en dire un peu plus ou donner un lien STP? Merci.

  8. #8
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Il est difficile d'en dire plus. C'est comme ça.
    Quand tu crois surcharger une fonction issue d'une classe dont tu hérites, en fait tu ne surcharges pas, mais tu masques la fonction qui devient alors indisponible directement.

    C'est tout c'est comme ça. Ce devrait être traité dans n'importe quel bouquin/cours a priori.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    54
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2004
    Messages : 54
    Points : 76
    Points
    76
    Par défaut
    Citation Envoyé par Luc Hermitte
    Il est difficile d'en dire plus. C'est comme ça.
    Quand tu crois surcharger une fonction issue d'une classe dont tu hérites, en fait tu ne surcharges pas, mais tu masques la fonction qui devient alors indisponible directement.

    C'est tout c'est comme ça. Ce devrait être traité dans n'importe quel bouquin/cours a priori.
    Bon, d'accord, mais quand même.. Pourquoi son code ne fonctionne-t-il pas alors? Et qu'est ce que le using a à voir là dedans (un exemple serait le bienvenu).
    J'ai regardé dans différents cours sur le net, j'ai rien trouvé là dessus.

  10. #10
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    struct A &#123;
       void f&#40;float&#41;;
    &#125;;
     
    struct B &#58; A&#123;
        void f&#40;int&#41;;
    &#125;;
    ...
    B b;
    b.f&#40;12.42&#41;; // pas content!!
    B::f(int) masque A::f(float);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct A &#123;
       void f&#40;float&#41;;
    &#125;;
     
    struct B &#58; A&#123;
        using A&#58;&#58;f;
        void f&#40;int&#41;;
    &#125;;
    ...
    B b;
    b.f&#40;12.42&#41;; // content!!
    On réimporte A::f(float) dans B.


    Et son code me semble assez correspondre à se cas de figure.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  11. #11
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut
    je n'ai pas réussi à utiliser le "using", à chaque fois le compilo n'était pas content...
    Du coup, j'ai réussi à modifier mon template, pour que ça marche, en servant de l'opérateur de résolution de portée.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    AbstractClient
    &#123;
       template < typename ClientToCall, typename FrameSpe > void checkFrame&#40; Frame* pFrame&#41; 
       &#123; 
          if &#40; FrameSpe* pFrameSpe = dynamic_cast<FrameSpe*>&#40;pFrame&#41; &#41;
          &#123;
             if &#40; ClientToCall* pClient = dynamic_cast<ClientToCall*>&#40;this&#41; &#41;
             &#123;
                pClient->processFrame&#40; pFrameSpe &#41;;
             &#125;
          &#125;
       &#125; 
    &#125;;
    et donc le ConcretClient :
    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
     
    class ConcreteClient 
    &#123; 
       void processFrame&#40; Frame* pFrame &#41; 
       &#123; 
          checkFrame<ConcreteClient, FrameToto>&#40;pFrame&#41;; 
          checkFrame<ConcreteClient, FrameTata>&#40;pFrame&#41;; 
          checkFrame<ConcreteClient, FrameTiti>&#40;pFrame&#41;; 
       &#125; 
     
       // fonction qui traite les FrameToto 
       void processFrame&#40; FrameToto* pFrame&#41; 
       &#123; // faire quelque chose avec des FrameToto &#125; 
     
       // fonction qui traite les FrameTata 
       void processFrame&#40; FrameTata* pFrame&#41; 
       &#123; // faire quelque chose avec des FrameTata &#125; 
     
    &#125;;

    Voila, ça marche !
    Merci à tous.

  12. #12
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    54
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2004
    Messages : 54
    Points : 76
    Points
    76
    Par défaut
    Citation Envoyé par Luc Hermitte
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    struct A &#123;
       void f&#40;float&#41;;
    &#125;;
     
    struct B &#58; A&#123;
        void f&#40;int&#41;;
    &#125;;
    ...
    B b;
    b.f&#40;12.42&#41;; // pas content!!
    B::f(int) masque A::f(float);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct A &#123;
       void f&#40;float&#41;;
    &#125;;
     
    struct B &#58; A&#123;
        using A&#58;&#58;f;
        void f&#40;int&#41;;
    &#125;;
    ...
    B b;
    b.f&#40;12.42&#41;; // content!!
    On réimporte A::f(float) dans B.


    Et son code me semble assez correspondre à se cas de figure.
    A ok, je ne suis pas certain que cela corresponde quand même à son cas de figure (il a déjà surchargé son void processFrame( Frame* pFrame ) ) mais au moins j'ai appris quelque chose. Merci

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

Discussions similaires

  1. Quelle est la pire libraire Open Source portée de Java vers .Net ?
    Par Invité dans le forum Général Dotnet
    Réponses: 1
    Dernier message: 30/03/2012, 17h51
  2. Réponses: 13
    Dernier message: 03/03/2008, 20h22
  3. Quelle est la portée d'une variable dans une page ASP ?
    Par sauceaupistou dans le forum ASP
    Réponses: 3
    Dernier message: 19/03/2007, 19h16
  4. Quelle est la fiabilité du protocole SSL ?
    Par Anonymous dans le forum Développement
    Réponses: 5
    Dernier message: 05/09/2002, 14h31

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