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 :

surcharge d'opérateur et polymorphisme


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Avril 2006
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2006
    Messages : 26
    Par défaut surcharge d'opérateur et polymorphisme
    Bonjour,

    Je viens du monde Java et C. J'ai tout naturellement eu l'idée d'en "fusionner" la puissance via le C++.

    Je me heurte à un petit soucis avec la surcharge d'opérateur et le polymorphisme.

    Imaginons le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    class A{
       public :
          virtual int& operator() (int x, int y) = 0;
    };
     
    class B : public A{
       private :
          int maVal;
       public :
          int& operator() (int x, int y){ return &maVal; }
    };
    L'idée étant de spécifier, via la classe abstraite A que les classes l'implémentant doivent proposer l'opérateur () pour l'accès à leur données. Et donc, puissent être utilisées ainsi, quelque soit l'implémentation :
    Le problème étant que le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    ...
    A monObj = B();
    monObj(2, 1) = 3;
    ...
    ne compile pas, pour la simple raison que A étant virtuelle, elle ne peut être instanciée.
    Pour utiliser le polymorphisme, on doit ainsi utiliser les pointeurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    ...
    A *monObj = new B();
    //et donc, de fait :
    (*monObj)(2,1) = 3;
    ...
    L'idée étant de mettre en place un découplage de l'interface et l'implémentation (pour faciliter la migration vers une autre librairie par exemple) mais aussi d'embellir le code des couches supérieures via la surcharge d'opérateur.

    Y'a-t-il un moyen de concilier les deux, au moins en masquant le déréférencement du pointeur ?

    Merci d'avance.

  2. #2
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Avril 2006
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2006
    Messages : 26
    Par défaut
    Je pourrais évidemment créer une classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    class ptrA{
       private :
          A* ptr;
       public :
          ptrA(A* pa):ptr(pa){}
          ~ptrA(){delete ptr;}
          int& operator() (int x, int y){ return (*ptr)(x,y);}
    };
    On aurait alors :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    ptrA monObj(new B());
    monObj(2,1) = 3;
    Mais ça devient un peu bordélique...

  3. #3
    r0d
    r0d est actuellement connecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 294
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    permière remarque:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int& operator() (int x, int y){ return &maVal; }
    est incorrect (ça ne devrait pas compiler). Il faut faire comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int& operator() (int x, int y){ return maVal; }
    En effet, en c++, le référencement est caché. C'est la même chose lorsqu'on utilise une variable passée par référence en paramètre d'une fonction. Par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    // cette fonction:
    void UneFonction( const std::string & text );
     
    //va être utilisée ainsi:
    std::string monTexte;
    UneFonction( monTexte ); // référencement caché
    Pour le reste, je vais regarder ça de plus plus près et je reviens

  4. #4
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Avril 2006
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2006
    Messages : 26
    Par défaut
    Oui, au temps (ou autant, c'est un long débat !) pour moi pour le référencement

  5. #5
    r0d
    r0d est actuellement connecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 294
    Billets dans le blog
    2
    Par défaut
    Je n'arrive pas bien à cerner ton problème.
    Dans ton premier post tu proposes le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    A monObj = B();
    monObj(2, 1) = 3;
    qui ne fonctionne pas puisque A est abstraite.
    Pourquoi ne pas faire, tout simplement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    B monObj;
    monObj(2, 1) = 3;
    ?

  6. #6
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Tu peux toujours utiliser une référence pour masquer le pointeur:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    A* pObj = new B();
    {
    	A& obj = *pObj;
    	obj(2, 1) = 3;
    }
    delete pObj;
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    r0d
    r0d est actuellement connecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 294
    Billets dans le blog
    2
    Par défaut
    Sinon, si c'est juste un problème de notation, tu peux utiliser une fonction membre plutôt qu'un opérateur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class A
    {
       virtual int& GetElement( int x, int y) = 0;
    };
     
    class B : public A
    {
       int& GetElement( int x, int y);
    };
    Ainsi, pour l'utiliser, ça donnera quelque chose comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    A* b = new B();
    b->GetElement(x,y);
    En fait, perso j'utilise très peu les opérateurs (et de moins en moins), car bien souvent ils ne permettent pas d'apporter la sématique nécessaire à un code limpide.

  8. #8
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Avril 2006
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2006
    Messages : 26
    Par défaut
    Citation Envoyé par r0d Voir le message
    Je n'arrive pas bien à cerner ton problème.
    Dans ton premier post tu proposes le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    A monObj = B();
    monObj(2, 1) = 3;
    qui ne fonctionne pas puisque A est abstraite.
    Pourquoi ne pas faire, tout simplement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    B monObj;
    monObj(2, 1) = 3;
    ?
    L'idée, c'est que l'implémentation de B n'étant pas tout à fait fixée (je risque de changer de librairie) j'utilise A pour en spécifier l'interface, via le polymorphisme. Ainsi, dans tout le reste de mon code, je manipule des A. Si je veux changer B (qui par exemple utilise la librairie CImg) pour C (qui utilise OpenCV) dérivant aussi de A, les modifications seront minimes avec ce procédé.

    Il est clair qu'utiliser une fonction comme tu le proposes est une possibilité, mais je préfèrerais (c'est plus joli) utiliser un opérateur surchargé.

    Si c'est la seule solution, je vais opter pour le couple A plus la classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    class ptrA{
       private :
          A* ptr;
       public :
          ptrA(A* pa):ptr(pa){}
          ~ptrA(){delete ptr;}
          int& operator() (int x, int y){return (*ptr)(x,y);}
    };
    Afin d'avoir le comportement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    ptrA monObj(new B());
    monObj(2,1) = 3;
    Comme je le décrivais précédemment. C'est assez lourd, y compris au niveau de la pile d'appels, mais plus élégant à l'utilisation.

    C'est vraiment dommage que le concept d'interface de Java n'existe pas en C++. Dès que j'aurais le temps, je regarderai si cela a été intégré au langage D.

  9. #9
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Avril 2006
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2006
    Messages : 26
    Par défaut
    Voilà, c'est programmé.
    C'est joli, ça se comporte très bien.

    MAIS.

    Les performances prennent une certaine claque, comparément à du C, à algo strictement équivalent : le coût moyen en temps est doublé.

    En conclusion donc, ce fût un exercice de style intéressant, ravivant une énième fois cette éternelle question personnelle qui est : "comment concilier POO et performance ?"

    Merci en tous cas à tous pour votre disponibilité !

    [résolu]

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

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. [C#] Tri d'objet et surcharge d'opérateur
    Par Royd938 dans le forum Windows Forms
    Réponses: 6
    Dernier message: 17/12/2007, 00h26
  3. Problème de surcharge d'opérateurs
    Par Hell dans le forum C++
    Réponses: 17
    Dernier message: 17/01/2005, 16h01
  4. Cumul de surcharges d'opérateurs
    Par Nats dans le forum C++
    Réponses: 2
    Dernier message: 11/10/2004, 13h37
  5. [VB .NET] Surcharge d'opérateur
    Par Franckintosh dans le forum VB.NET
    Réponses: 2
    Dernier message: 07/09/2004, 19h05

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