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 :

[Polymorphisme] Opérateur polymorphique


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Avatar de méphistopheles
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 551
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 551
    Par défaut [Polymorphisme] Opérateur polymorphique
    Bonjour.

    J'ai créé une classe B qui hérite d'une classe A. Or A, à déjà une fonction avec l'opérateur == (définie pour une classe A).
    J'ai surchergé cet opérateur dans la classe B avec un operator==(B &).
    ma question porte donc sur le renvoi de A==B(A) et B(A)==B.

    concrètement:
    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:
       int varA;
     
       A(arguments &args);
       A(A &a);
     
       bool operator==( const A &a)const;
    }
    class B : public A {
    public:
       int varB;
     
       B( const int &varb, arguments & args):A(args),varB(varb){}  
       B( const int &varb, A & a):A(a),varB(varb){}
       B(B & b);
     
       bool operator==(const B &b)const
       {
           return (varB=b.varB && A::operator==(B));
       }
    }
    la question est: que se passe-t'il lors du code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    A an_A;
    B an_B;
    int I;//I quelquonque
     
    bool reponse;
    reponse=(an_A==A(an_A)); //renvoie true
    reponse=(an_B==B(an_B)); //renvoie true
    reponse=(an_A==B(an_A,I)); //renvoie ?
    reponse=(B(an_A,I)==an_A); //renvoie ?
    reponse=(an_B==A(an_B)); //renvoie ?
    reponse=(A(an_B)==an_B); //renvoie ?

    Merci de vos réponses

  2. #2
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    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 296
    Par défaut
    Dans la théorie bridée-OO, tu peux passer beaucoup de temps à essayer de résoudre ce genre de question. En Java, ils en sont arrivés à 2 écoles.

    En pratique, tu fais du C++ qui te permet de définir proprement des classes à sémantique de valeur, ainsi qu'une généricité fortement typée (pas d'héritage depuis un type racine unique à la void*). Ce genre de question ne se pose pas en C++ : la sémantique de valeur (en particulier l'égalité dans le cas qui nous intéresse ici) est incompatible avec les hiérarchies polymorphes (dans les 10 premières approximations)

    Comprendre: l'expérience nous apprend que l'on n'a jamais besoin de connaitre la réponse à cette question, et qu'à chercher on va finir par tourner en rond.


    Sinon, peut-on dire que cela se résume à résoudre un problème de dispatch multiple ? Double pour être plus exact?
    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...

  3. #3
    Membre Expert
    Avatar de méphistopheles
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 551
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 551
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    Dans la théorie bridée-OO, tu peux passer beaucoup de temps à essayer de résoudre ce genre de question. En Java, ils en sont arrivés à 2 écoles.

    En pratique, tu fais du C++ qui te permet de définir proprement des classes à sémantique de valeur, ainsi qu'une généricité fortement typée (pas d'héritage depuis un type racine unique à la void*). Ce genre de question ne se pose pas en C++ : la sémantique de valeur (en particulier l'égalité dans le cas qui nous intéresse ici) est incompatible avec les hiérarchies polymorphes (dans les 10 premières approximations)

    Comprendre: l'expérience nous apprend que l'on n'a jamais besoin de connaitre la réponse à cette question, et qu'à chercher on va finir par tourner en rond.


    Sinon, peut-on dire que cela se résume à résoudre un problème de dispatch multiple ? Double pour être plus exact?
    Aie, beaucoup de termes techniques pour moi.... en réalité, il me semblais que l'incompatibilité n'existait que dans un sens (classe mere =>classe fille) et étais automatique dans l'autre, aussi me semblais-t'il que je n'avais besoin que d'un opérateur supplémentaire dans la classe fille.... pour moi, le problème se pose car la classe A est en réalité "inconnue " (template)...

    sinon, qu'est-ce qu'un dispatch ?


    à koala01: oui, j'avoue que dans le cas d'un int l'économie est minime voire négative. par contre, il me semble que ce genre de prise de paramètre est rentable, à partir d'un int en entree un int en sortie (mieux vaut deux pointeurs en entrée et une sortie void, on évite ainsi la création d'une varaible locale)... enfin je suis pas sûr, mais vu qu'un pointeur a la taille d'un int...

  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
    Citation Envoyé par méphistopheles Voir le message
    <snip>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    /* <sniped code> */
    class B : public A {
    public:
       int varB;
     
       B( const int &varb, arguments & args):A(args),varB(varb){}  
       B( const int &varb, A & a):A(a),varB(varb){}
    /* more code */
    Quand je vois ces quelque lignes, je ne peux m'empêcher de crier "à l'infamie"... (bon, je peux peut-être ne pas aller jusque là, je te l'accorde )

    Il ne sert en effet à rien de transmettre un type primitif sous la forme d'une référence si tu n'envisage pas de l'utiliser comme un argument "in-out" (comprend: dont la valeur modifiée au sein de la fonction sera répercutée sur la valeur dans la fonction appelante).

    Le fait de passer un type abstrait de donnée ("POD" ou "TAD") par référence a pour but d'en éviter la copie, qui peut être interdite (des type "non copiables"), ou qui peut réclamer énormément de ressources inutiles (un tableau alloué dynamiquement de 10.000 éléments) ou de temps de copie (TAD pour lequel la copie "membre à membre" n'est pas applicable).

    La copie de type primitifs (entiers, réels, booléens et pointeurs) ne pose a priori aucun problème de ce point de vue, les ressources nécessaires à la copie d'un type primitif étant... minimes et connues à l'avance.

    Les pointeurs peuvent justifier d'être passés par référence si l'idée est que le pointeur sera modifié dans la fonction appelée, pour éviter le recours aux... pointeurs de pointeurs.

    Typiquement, nous déclarerons un argument sous la forme d'une référence constante dans deux cas bien précis (bien que le deuxième soit - me semble-t-il destiné à être retiré de la prochaine norme):
    1. si la variable de la fonction appelante qui sert d'argument ne doit ou ne peut pas être modifiée dans la fonction appelée
    2. si l'on envisage de pouvoir passer une variable temporaire, dont, fatalement (du fait de la destruction de la variable temporaire au moment où la fonction appelée sera quittée) les modifications seront perdues... une fois que l'on reprend l'exécution de la fonction appelante
    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 émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Le fait de passer un type abstrait de donnée ("POD" ou "TAD") par référence a pour but d'en éviter la copie, qui peut être interdite (des type "non copiables"), ou qui peut réclamer énormément de ressources inutiles (un tableau alloué dynamiquement de 10.000 éléments) ou de temps de copie (TAD pour lequel la copie "membre à membre" n'est pas applicable).
    Remarque de terminologie : POD c'est Plain Old Data, et ça n'a rien avoir avec un TAD - type abstrait de données.

  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 méphistopheles Voir le message
    à koala01: oui, j'avoue que dans le cas d'un int l'économie est minime voire négative. par contre, il me semble que ce genre de prise de paramètre est rentable, à partir d'un int en entree un int en sortie (mieux vaut deux pointeurs en entrée et une sortie void, on évite ainsi la création d'une varaible locale)... enfin je suis pas sûr, mais vu qu'un pointeur a la taille d'un int...
    Il est des situations où le retour de fonction est indisponible pour le retour de l'entier - par exemple parce que la fonction peut renvoyer un booléen représentant la réussite global de ce que la fonction est sensée faire - ou parce qu'il y a des contraintes au niveau du prototype de la fonction.

    Il est donc pafrois nécessaire d'utiliser un type primitif sous la forme d'un parametre "in-out"...

    Dans ce cas, l'utilisation d'une référence (non constante) sera largement préférable à celle d'un pointeur, parce que l'utilisation de pointeurs doit être évitée "autant que possible".

    En C++ (il en va différemment en C, car le C ne connait pas les références), il est possible d'utiliser des pointeurs dans bien des cas, mais il est conseillé de ne le faire que quand... il faut les utiliser (que l'on n'a pas d'autre solution)

    Je n'ai personnellement aucun problème avec les pointeurs.

    Mais il est vrai que quand leur utilisation a uniquement pour but de permettre de répercuter une modification effectuée au sein d'une fonction appelée dans la fonction appelante, cela implique que l'utilisateur doit penser à "prendre l'adresse de la variable" d'un coté et qu'il faut penser à modifier "ce qui est pointé de l'autre".

    L'utilisation d'une référence dans ce cadre permet décrire dans la fonction appelée un code strictement identique à celui que nous aurions écrit dans la fonction appelante.
    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

  7. #7
    Membre Expert
    Avatar de méphistopheles
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 551
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 551
    Par défaut
    Citation Envoyé par koala01 Voir le message
    L'utilisation d'une référence dans ce cadre permet décrire dans la fonction appelée un code strictement identique à celui que nous aurions écrit dans la fonction appelante.
    He bien, c'est pour cela que j'utilise beaucoup les référence. Mon discurs sur les pointeurs étais lié au fait qu'il me semblais qu'utiliser les références revenait à utiliser , en C, des pointeurs (mais gérés par le compilo). Je me suis peut être fourvoyé.

    Concernant les opérateurs polymorphique, sinon, personne ne peut m'éclairer ?

    Le résultat que je souaite obtenir est d'avoir vrai dans toutes les comparaisons citées dans le premier message, et ce sachant que je ne peut modifier la classe A...



    merci

  8. #8
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Pourquoi _dois-tu_ faire en sorte que tous ces tests soient vrais ?

    Parce que comparer des objets de types différents en faisant en sortie qu'ils puissent être égaux, c'est très farfelu voir erronné

Discussions similaires

  1. polymorphisme et surcharge des opérateurs
    Par j.david dans le forum Langages de programmation
    Réponses: 1
    Dernier message: 02/01/2011, 19h17
  2. surcharge d'opérateur et polymorphisme
    Par Kyrel dans le forum Débuter
    Réponses: 15
    Dernier message: 13/03/2009, 00h02
  3. Réponses: 15
    Dernier message: 25/01/2005, 16h51
  4. opérateur non applicable à ce type d'opérande
    Par Amon dans le forum Langage
    Réponses: 3
    Dernier message: 11/06/2003, 18h07
  5. [imprecis]Réaliser a^n avec seulement l'opérateur d'addition
    Par Amon dans le forum Algorithmes et structures de données
    Réponses: 18
    Dernier message: 08/11/2002, 22h22

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