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 :

problème de surcharge


Sujet :

C++

  1. #1
    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 problème de surcharge
    Bonjour a tous. Voici mon problème:

    En fait, je déclare 2 classes filles d'une classe de base.
    Ensuite, j'ai surchargé dans une 4eme classe une méthode, de sorte qu'elle agisse différement en fonction de la classe à laquelle appartient la donnéee passée en paramètre.

    En fait, cela donne qqch du genre:

    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 A
    {//...}
     
    class B : public class A
    {//...}
     
    class C : public class A
    {//...}
     
    class Z
    {
    //...
    process (A* obj);
    process (B* obj);
    process (C* obj);
    }
    L'appel à la fonction process se fait comme suit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    A* obj = create_obj(int blabla);//renvoie soit un B*, soit un C*
    process(obj);
    Le problème, c'est que c'est la méthode process (A* obj) qui est appelée, et pas
    process (B* obj) ni même process (C* obj).

    QQn a une solution?
    Faut-il que dans process (A* obj) je vérifie le type du paramètre et appelle la surharge correspondante?
    D'une manière plus générale, qqn sait-il où je peux trouver de la doc sur la façon dont fonctionne les surcharges?

  2. #2
    Membre expérimenté Avatar de 10_GOTO_10
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    887
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 887
    Points : 1 531
    Points
    1 531
    Par défaut Re: problème de surcharge
    Citation Envoyé par bountykiller
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    A* obj = create_obj(int blabla);//renvoie soit un B*, soit un C*
    Quel est le prototype de create_obj ? Elle ne peut pas renvoyer soit un B*, soit un C*. D'après la suite, je suppose qu'elle renvoie un A*. Donc quand tu fait:

    obj étant un A*, on appelle forcément la fonction process(A*).

    Va appeler la fonction process(B*). Mais cette façon de faire n'est pas très rigoureuse. Le mieux dans ce cas serait de définir la fonction process en virtuel dans la classe A (surchargée dans B et C), puis:



  3. #3
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Il faut faire de process une fonction virtuelle au lieu de créer une classe Z
    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
    class A 
    {
    public: 
    virtual void process (); //...
    } ;
     
    class B : public A 
    {
      virtual void process ();//...
    } ;
     
    class C : public A 
    {
    virtual void process ();//...
    };
      void A::process () {...}
      void B::process () {...}
      void C::process () {...}
     
    .... 
    A* obj = create_obj(int blabla);//renvoie soit un B*, soit un C*
    obj->process ();

  4. #4
    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
    Certes, mais dans mon cas ce n'est pas possible. En fait, je n'est pas une seule classe Z, mais un certain nombre (assez important). Chacune d'entre elle peut en plus agir différement en fonction de l'état dans lequel elle se trouve (entendre par là la valeur de certains de ces membres), donc le fait de multiplier les fonctions de type A->process(), B->process() et C->process() ne me parait pas approprié.

    10_GOTO_10> Oui, le prototype de create_obj est bien A*create_obj(int blabla). Mais en fait il renvoie toujours soit un B*, soit un C*. (A* est leur ancre commun le plus proche)

    Maintenant une simple question:
    La surcharge qu'il faut appeler est-elle évaluée de façon statique (ce qui peut expliquer mon problème) ou dynamique (et dans ce cas quelles sont les règles qui s'appliquent)?
    Si elle est statique, y a-t-il moyen de la rendre dynamique?

    Merci pour vos réponses.

  5. #5
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 279
    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 279
    Points : 11 015
    Points
    11 015
    Par défaut
    La surcharge est un sucre syntaxique résolu à la compilation. 200% statique.
    La redéfinition proposée diogene est à la base de la solution.

    Peut-être en jongleant avec le pattern visiteur et en donnant éventuellement des noms plus explicites aux fonctions. Mais on garde la fonction virtuelle pour décider d'à qui on dispatche. A voir.

  6. #6
    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
    Non, la solution de faire un obj->Process() ne convient pas entre autres parce cela rendrait le code plus complexe en fait.
    Maintenant, si la surcharge est un mécanisme évalué statiquement, je crois que je vais devoir jouer avec les opérateurs de cast (en tout cas c'est ce qui me parait le plus simple).

    faire un truc du style:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void z::process (A* obj)
    {
      if (B* b_tmp = dynamic_cast<B*>(obj) )
        process(b_tmp);
      else if (C* c_tmp = dynamic_cast<C*>(obj) )
        process(c_tmp);
      else 
        //Erreur
    }

  7. #7
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 279
    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 279
    Points : 11 015
    Points
    11 015
    Par défaut
    Plus complexe ?!?!?!
    Non!!!!!!!
    Ce dynamic cast est une horreur. Surtout où il est idiomatique de passer par la liaison tardive -- et en plus, c'est plus lent, moins maintenable, ...

  8. #8
    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
    Si plus complexe parce que (comme je l'ai dit plus haut) j' ai en fait un grand nombre de classe qui fonctionne comme la classe Z.
    Je devrai alors faire des trucs du style:

    A->process_Z1();
    A->process_Z2();
    A->process_Z3();
    A->process_Z4();
    A->process_Z5();
    A->process_Z6();
    ...
    Pareil por B et C, pas top.
    Ensuite, les 3/4 des champs auxquels accède cette fonction sont des champs privés de Z1, Z2, Z3...
    Sans parler du fait que Z1, Z2, Z3... dérivent de la même classe, sont regroupés dans le même fichiers, font chacun à leur tour des appels vers des fonctions des autres classes Z1, Z2, Z3, .... Bref, cette solution ne convient pas. (a oui, le comportement de cette fonction va aussi fortement dépendre de l'etat de l'objet Zx)

    Maitenant, dire que ce mon dynamic cast est une horreur, je veux bien mais si tu as une autre solution, je suis preneur. C'est plus lent, je sais. Moins maitenable????? ça j'en doute fort.

  9. #9
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 279
    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 279
    Points : 11 015
    Points
    11 015
    Par défaut
    Hum. Deux choses.

    A- D'abord, en supposant qu'il n'y ait qu'une seule classe Z, ou plus précisément un ensemble de classes qui ne sont pas toutes tirées de la même hiérarchie, et dont les objets ne sont pas manipulés comme des représentants d'une classe racine Z0, alors, LA SOLUTION TYPE est de passer par des fonctions virtuelles comme cela t'a été montré.
    Dans tous les cas, avoir des surcharges f(Z1), f(Z2), ...ou f1(Z1) f2(Z2) ne change strictement : il faut écrire les fonctions. Tu n'y couperas pas.

    La surcharge n'est qu'un sucre syntaxique. Comprendre : une facilité d'écriture dépourvue de dynamisme et résolue à la compilation.

    Le dynamisme est dans le "polymorphisme d'inclusion" (aka d'héritage, ...), soit en C++ en passant par des fonctions virtuelles.

    Le dynamic_cast<> n'est pas maintenable dans le sens où tu ne peux pas te contenter de rajouter des nouveaux objets pour prendre en compte de nouveaux types, il faut aussi traquer toutes les utilisations du dynamic_cast pour n'en manquer aucune afin d'étendre les simili-switch. Il est extrêmement facile d'en oublier. Soit, c'est pas super maintenable. Ce n'est pas évolutif, ...


    B- Maintenant, dans tes deux derniers messages, j'ai l'impression qu'un détail important n'avait pas été signalé. Ne disposerais-tu pas de deux hiérarchies et de fonctions qui se doivent d'être polymorphes simultanément sur les deux hiérarchies ? (ou plus simplement qui doivent être polymorphes au regard de deux paramètres issus de hiérarchie(s))
    Si c'est bien le cas, oriente tes recherches vers "double dispatch" ou "multi-methods" en C++. Un chapitre y est dédié dans Modern C++ Design.
    En C++, l'emploi du dynamic_cast<> est alors effectivement au centre de certaines des solutions idiomatiques à ce problème.

    Maintenant, si ton polymorphisme ne concerne qu'un seul paramètre (explicite ou implicte (this)) de tes fonctions, alors tu n'as très certainement pas besoin du dynamic_cast, les fonctions virtuelles (surchargées pour tous les Z possibles s'il le faut) sont la solution.



    Là j'avoue que je ne suis pas sûr si tu maitrises bien le polymorphisme ou si des détails propres à ton vrai problème ne serait pas passés inaperçus dans la discussion.

Discussions similaires

  1. Problème de surcharge de l'opérateur <<
    Par Kr00pS dans le forum C++
    Réponses: 4
    Dernier message: 22/02/2007, 19h10
  2. Débutant, problème de surcharge
    Par guidevelop dans le forum C++
    Réponses: 5
    Dernier message: 06/11/2006, 14h28
  3. Petit probléme de surcharge d'opérateur .
    Par Clad3 dans le forum C++
    Réponses: 20
    Dernier message: 11/04/2005, 20h15
  4. Problème de surcharge d'opérateurs
    Par Hell dans le forum C++
    Réponses: 17
    Dernier message: 17/01/2005, 16h01
  5. Réponses: 2
    Dernier message: 25/07/2004, 23h24

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