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 et const


Sujet :

C++

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2011
    Messages : 6
    Points : 5
    Points
    5
    Par défaut Polymorphisme et const
    Bonjour à vous,

    Avant de oser cette question, j'ai fait mes recherches mais sans résultat précis. Je vous la pose donc...

    Je fais mes premières armes en polymorphisme. J'ai bien compris que le polymorphisme passe par la redéfinition exacte d'une fonction virtuelle déclarée dans la classe de base. J'ai également compris que l'argument de cette fonction doit être un pointeur ou un référence à un objet afin que l'on ait pas plus à faire à une simple redéfinition qu'à du polymorphisme.

    Par contre, je me demande si il est OBLIGATOIRE de passer l'argument comme constant pour que se mette en place le polymorphisme. Je me pose la question car tous les exemples que j'ai vu font usage de const.

    Cela me pose problème car le fait de déclarer mon argument const m'empêche, pour une raison qui m'est obscure, de faire appel aux accesseurs de la classe ou est redéfinie la fonction virtuelle. Voici un bout de code...
    Selon vous, est-il correct côté polymorphisme?

    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
    TravailleurAutonome::TravailleurAutonome(string nom, string prenom, int tarif) : Travailleur(nom, prenom) {
     
    		setTarif(tarif);
    }
     
    TravailleurAutonome::TravailleurAutonome(TravailleurAutonome & t):Travailleur(t) {
     
    		setTarif(t.getTarif());
    }
     
    // Pas de const sinon getPrenom, getNom et getTarif ne fonctionnent pas
    // afficherTravailleurVirtuelle est déclarée et définie dans la classe travailleur
    // également sans const
    void TravailleurAutonome::afficherTravailleurVirtuelle() 
    {
    		cout<<getPrenomTravailleur()<<" ";
    		cout<<getNomTravailleur();
                    cout<<endl<<getTarif();
     
    }
    Merci à l'avance!!

  2. #2
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Oui ca marche (*), mais dans ton exemple je doute de l'utilité des accesseurs, mettre les données membres en portée protégée. De même utiliser des mutateurs dans les constructeurs est un peu étrange, utiliser la liste d'initialisation devrait suffir dans la grande majorité des cas.

    (*) Il n'y a pas vraiment de rapport en const et le polymorphisme, l'un définie un mécanisme et l'autre un autre, ils coexistent sans contraintes.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2011
    Messages : 6
    Points : 5
    Points
    5
    Par défaut Merci
    Merci pour ta réponse rapide!! Tu me rassure sur l'utilisation de ce mécanisme de polymorphisme. Pour ce qui est de l'utilisation des accesseurs pour les données membres, on m'a dit que c'était une pratique recommandée en fonction du design patern "Self Encapsulated" que d'utiliser les accesseurs, autant dans le .cpp d'une classe qu'à l'extérieur de celle-ci.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    En fait, la "const correctness" et le polymorphisme sont deux aspects tout à fait distincts...

    Le but de la "const correctness" est de s'assurer, au travers d'un "contrat" que l'on prend avec le compilateur, qu'un objet ne sera pas modifié s'il n'y a pas lieu qu'il le soit.

    Pour y arriver, il y a deux points à mettre en oeuvre :
    Rendre constantes toutes les fonctions qui ne doivent pas modifier l'objet au départ duquel elles sont appelées :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class MaClass
    {
        public:
            /* si on essaye de modifier l'objet dans la fonction ci-dessous, 
             * le compilateur ne sera pas d'accord parce que la doSomething
             * s'engage à ne pas modifier l'objet
             */
            void doSomething() const ;
    };
    utiliser des objets constants chaque fois qu'ils n'ont pas vocation à être modifiés:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void foo(MaClass const & mc)
    {
        /*...*/
    }
    En effet, si l'on travaille avec un(e référence sur un) objet constant, seules les fonctions qui se seront engagées à ne pas modifier l'objet pourront être invoquées car on peut invoquer une fonction constante depuis n'importe quel objet, mais on ne peut invoquer que des fonctions constantes depuis un objet constant

    D'un autre coté, il y a le polymorphisme, c'est à dire la capacité de faire passer un objet de type dérivé comme "étant du type de base" tout en gardant le comportement propre au type dérivé.

    Cette capacité ne peut être assurée que lorsque les objets sont transmis par pointeurs ou par références.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void foo(Base /* const  */&  b)
    {
        b.truc(); // invoque le comportement correspondant au type réel
                  // de l'objet passant pour être du type de base
    }
    void foo(Base * ptr)
    {
        ptr->truc(); // invoque le comportement correspondant au type réel
                     // de l'objet passant pour être du type de base
    }
    Enfin, il faut savoir que l'utilisation de références constante a l'énorme avantage de permettre la création de ce que l'on appelle des variables temporaires anonymes:
    Il s'agit de variables qui ne seront créées (grâce à l'existence du constructeur adéquat) uniquement pour la durée de l'exécution de la fonction que l'on invoque:
    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 Truc
    {
        public:
            Truc(int i);
    }
    void foo(Truc const & t)
    {
         /* ... */
    }
    int main()
    {
        foo(5); // on va créer une variable de type Truc pour laquelle on invoque
                // le constructeur Truc(5) et qui ne sera utilisable que pour la durée
                // de l'exécution de foo
        return  0;
    }
    Cette pratique est acceptée parce que :
    • une référence est un alias sur un objet existant
    • on sait par avance que l'objet ne sera pas modifié, ce qui ne servirait quand même à rien, vu que le dit objet sera quand même perdu une fois sorti de foo
    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
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2011
    Messages : 6
    Points : 5
    Points
    5
    Par défaut Merci
    Merci beaucoup koala01 pour ces bonnes indications. Tu m'as fait allumer sur pourquoi je ne peux pas invoquer mes accesseurs à partir de la fonction constante... il faut que ces accesseurs soit aussi constants!! Bien sûr........

    Merci encore

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

Discussions similaires

  1. const et polymorphisme
    Par hibou107 dans le forum Débuter
    Réponses: 3
    Dernier message: 22/06/2011, 00h54
  2. Surcharge et Polymorphisme
    Par Hell dans le forum C++
    Réponses: 6
    Dernier message: 12/01/2005, 20h50
  3. Pb d'nitialisation d'un const char*
    Par davkick dans le forum C++
    Réponses: 9
    Dernier message: 09/12/2004, 16h27
  4. Réponses: 2
    Dernier message: 25/07/2004, 23h24
  5. Chaines et pointeurs mais pas "const"
    Par hpfx dans le forum C
    Réponses: 9
    Dernier message: 05/10/2003, 20h23

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