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 :

qu'est ce que permet virtual?


Sujet :

C++

  1. #1
    Membre du Club
    Homme Profil pro
    touristepationné
    Inscrit en
    Janvier 2012
    Messages
    132
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : touristepationné
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 132
    Points : 57
    Points
    57
    Par défaut qu'est ce que permet virtual?
    Bonjour,

    Apres plusieurs recherche, je ne parviens pas à comprendre le fonctionnement du mot clef "virtual". Quelqu'un aurait-il un exemple très simple (j'insiste vraiment je suis très novice) de son utilisation, s'il vous plait?

    Merci par avance.

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Ce qu'il permet, d'un point de vue syntaxe :
    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
    class A
    {
      void f() {cout << "A::f" << endl;}
      virtual void g() {cout << "A::g" << endl;}
    };
    class B : public A
    {
      void f() {cout << "B::f" << endl;}
      virtual void g() {cout << "B::g" << endl;}
    };
    int main()
    {
      B b;
      A* pa = &b;
      B* pb = &b;
      pa->f();
      pa->g();
      pb->f();
      pb->g();
    }
    D'un point de vue utilité, il permet de gérer des objets différents par l'intermédiaire d'une interface commune, tout en permettant à ces objets d'effectuer des actions différentes pour réaliser cette interface.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Membre du Club
    Homme Profil pro
    touristepationné
    Inscrit en
    Janvier 2012
    Messages
    132
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : touristepationné
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 132
    Points : 57
    Points
    57
    Par défaut
    j'obtiens comme résultats:
    A::f
    B::g
    B::f
    B::g
    je m'attendais à obtenir:
    A::f
    A::g
    B::f
    B::g
    Pourquoi c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     virtual void g() {cout << "B::g" << endl;}
    qui intervient?

    Est-on obliger d'écrire 2 fois virtual? ou une seule devant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     virtual void g() {cout << "B::g" << endl;}
    aurait suffit?

  4. #4
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,

    Une méthode virtuelle peut être redéfinie dans les classes filles.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    B b;
    A* pa = &b;
    B* pb = &b;
    pa->f(); // f() non virtuelle, donc appel de A::f();
    pa->g(); // g() virtuelle, pa est de type A* (typage statique) mais pointe sur un objet de type B (typage dynamique), c'est donc B::g() qui est appelée.
    Est-on obliger d'écrire 2 fois virtual? ou une seule devant
    Il faut bien l'écrire 2 fois.
    (Au minimum dans la classe de base (A ici), il me semble pas qu'indiquer "virtual" ou non dans les classes dérivées ne change quelque chose).

  5. #5
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par B65AcR Voir le message

    Pourquoi c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     virtual void g() {cout << "B::g" << endl;}
    qui intervient?
    Parce que g est virtual

    Quand tu considère pa, son type statique, la manière dont il est déclaré dans le programme, c'est pointeur sur un objet de type A. Mais en réalité, il pointe sur un objet de type B. Si on appelle une fonction classique sur pa, c'est son type statique qui va déterminer quelle fonction est vraiment appelée. Si la fonction est virtuelle, on va regarder le type de l'objet sur lequel on pointe réellement pour déterminer la fonction appelée.
    Citation Envoyé par B65AcR Voir le message
    Est-on obliger d'écrire 2 fois virtual? ou une seule devant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     virtual void g() {cout << "B::g" << endl;}
    aurait suffit?
    Ni l'un, ni l'autre : Une seule fois est nécessaire, mais au niveau de la classe de base. Ceci dit, il est généralement utile quand on lit une classe dérivée de savoir si on redéfini une fonction de la classe de base ou pas. Il est donc préférable de re-préciser virtual dans la classe dérivée, ou en C++11 d'utiliser le mot clef override pour cela.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  6. #6
    Membre du Club
    Homme Profil pro
    touristepationné
    Inscrit en
    Janvier 2012
    Messages
    132
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : touristepationné
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 132
    Points : 57
    Points
    57
    Par défaut
    ok!! Je crois que je comprends ou vous voulez en venir.
    Un typage dynaique est un typage qui se préoccupe du type réel de l'objet?
    Ceci dit, il est généralement utile quand on lit une classe dérivée de savoir si on redéfini une fonction de la classe de base ou pas. Il est donc préférable de re-préciser virtual dans la classe dérivée
    Je ne comprends pas...

  7. #7
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par B65AcR Voir le message
    ok!! Je crois que je comprends ou vous voulez en venir.
    Un typage dynaique est un typage qui se préoccupe du type réel de l'objet?
    Oui.
    Citation Envoyé par B65AcR Voir le message
    Je ne comprends pas...
    Quand dans une classe dérivée, on déclare une fonction ayant le même nom et les mêmes arguments qu'une fonction virtuelle de la classe de base, on dit qu'on redéfinit la fonction de la classe de base (puisque du point de vue de la classe dérivée, tout se passera comme si la fonction de la classe de base avait été remplacée par la nouvelle version). Dit plus simplement, virtual dans la classe dérivée n'est pas obligatorie, mais recommandé (ou alors, l'utilisation d'override).
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  8. #8
    Membre du Club
    Homme Profil pro
    touristepationné
    Inscrit en
    Janvier 2012
    Messages
    132
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : touristepationné
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 132
    Points : 57
    Points
    57
    Par défaut
    Merci, cette fois j'ai compris.

    Une petite precision tout de meme. Virtual permet de la flexibilité dans les cas ou on ne peut pas connaitre à l'avance le type réel de l'objet?

    Dans notre exemple, au lieu d'appeler pa g(), on aurait pu directement appeler pbg()? Cela aurait été plus rigoureux?

  9. #9
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    virtual permet de trimballer un pointeur sur une classe de base, et lors de l'appel d'une méthode appliqué à ce pointeur, d'appeler en réalité la méthode implémentée dans l'objet dérivé.

    C'est par exemple pratique quand tu as un vecteur de pointeurs vers une classe de base, et que tu souhaites appeler un même nom de méthode pour chacun des éléments.
    Selon le type réel (déterminé dynamiquement), la bonne méthode (= la bonne définition) sera appelée.

  10. #10
    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,

    Le mot clé virtual indique au compilateur que l'on risque de redéfinir le comportement de la fonction dans les classes dérivées. Il a pour résultat de mettre en place toute une mécanique qui permet de le faire .

    Dans une relation d'héritage (il n'a de sens qu'avec une telle relation), il permet d'obtenir ce que l'on appelle un comportement polymorphe, c'est à dire un comportement qui s'adaptera au type réel de la donnée manipulée même s'il s'agit d'une référence (ou un pointeur) sur la classe de base. C'est la base de la substituabilité, qui est l'ajout essentiel de la programmation orientée objet par rapport à la programmation purement procédurale
    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

  11. #11
    Membre du Club
    Homme Profil pro
    touristepationné
    Inscrit en
    Janvier 2012
    Messages
    132
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : touristepationné
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 132
    Points : 57
    Points
    57
    Par défaut
    Hormis pour jouer des conversions implicites, ça pourrait etre une bonne idée de virtualiser toutes ses fonctions? Ou ce n'est pas a faire pour eviter les erreurs et garder en lisibilité?

  12. #12
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Salut,

    tout virtualiser, c'est le parti pris de certains langages. Pour ma part, je suis contre.
    Un virtual ça a un coût, pas forcément énorme, souvent négligeable, mais ça a un coût. Et ça reste une fonctionnalité qui modifie un peu ce que fait ton code.
    La philosophie C++ est que tu ne payes que ce que tu écris/demandes/codes. Ce que je trouve vraiment bien AMHA.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  13. #13
    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
    Citation Envoyé par B65AcR Voir le message
    Hormis pour jouer des conversions implicites, ça pourrait etre une bonne idée de virtualiser toutes ses fonctions? Ou ce n'est pas a faire pour eviter les erreurs et garder en lisibilité?
    Citation Envoyé par Bousk Voir le message
    Salut,

    tout virtualiser, c'est le parti pris de certains langages.
    Pour ma part, je suis contre.
    Un virtual ça a un coût, pas forcément énorme, mais ça a un coût.
    Le C++ a cela de bien que, tu ne payes que ce que tu écris/demandes/codes.
    Bousk a tout à fait raison. Certains langages ont -- par nature -- besoin que toutes les fonctions soient virtuelles. Mais pas C++.

    Non seulement le fait de virtualiser une fonction a un cout en termes d'exécution, mais il faut te dire que la présence du mot clé virtual a une signification pour l'utilisateur de la classe, très semblable à la signification qu'il prend pour le compilateur : je peux, en cas de besoin, redéfinir le comportement de la fonction pour qu'il soit plus adapté au type réel de l'objet.

    Pour certaines fonctions, cela a du sens de donner cette possibilité, pour d'autres, cela n'en a absolument pas
    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

  14. #14
    Membre du Club
    Homme Profil pro
    touristepationné
    Inscrit en
    Janvier 2012
    Messages
    132
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : touristepationné
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 132
    Points : 57
    Points
    57
    Par défaut
    Merci pour vos réponses.

    je peux, en cas de besoin, redéfinir le comportement de la fonction pour qu'il soit plus adapté au type réel de l'objet.
    On rentre ici dans un domaine que je n'est encore jamais abordé. Aurais tu un exemple très simple à comprendre?

  15. #15
    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
    Si tu n'as pas encore abordé le problème, il vaut peut etre mieux attendre que tu aies un peu avancé dans le cours/le tutoriel que tu suis.

    Pour arriver à comprendre le principe, il faut que tu comprennes ce qu'est un héritage. Les choses deviendront claires d'elles meme une fois que tu auras abordé cette partie de ton cours / tutoriel. Mais, entre temps, cela ne ferait que te déconcerter d'avantage
    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

  16. #16
    Membre du Club
    Homme Profil pro
    touristepationné
    Inscrit en
    Janvier 2012
    Messages
    132
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : touristepationné
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 132
    Points : 57
    Points
    57
    Par défaut
    Déconcentré moi?

    J'ai vu les héritages. une personne hors forum m'a répondu. apparement, il serait question de choisir la bonne fonction entre 2 fonctions virtualisées. C'est ça la modif de la fonction?

  17. #17
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    B.A.-BA des cours de polymorphisme, exemple typique
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    struct Animal { virtual void cri() const=0; };
    struct Chat : Animal { virtual void cri() const { std::cout<<"miaou"<<std::endl; } };
    struct Chien : Animal { virtual void cri() const { std::cout<<"wouaf"<<std::endl; } };
     
    int main()
    {
      Animal* p = new Chat;
      p->cri();
      delete p;
      p = new Chien;
      p->cri();
      delete p;
      return 0;
    }
    http://lmgtfy.com/?q=polymorphisme
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  18. #18
    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
    Bon, l'héritage public est la relation la plus forte qui puisse exister entre deux classes. C'est une relation EST-UN, au sens sémantique du terme (une voiture ou un camion EST-UN véhicule, un rectangle, un cercle ou un triangle EST-UN(e) forme géométrique, ...).

    Il y a certaines règles à respecter pour pouvoir utiliser l'héritage, ce qui fait que, contrairement à ce que l'on apprend à l'école, la classe Carré ne peut pas hériter de la classe Rectangle, mais nous y reviendrons un peu plus tard si besoin en est

    La classe de base (Vehicule ou FormeGeometrique, pour respecter les deux exemples que j'ai cités) présente un certain nombre de comportements communs à l'ensemble des classes qui peuvent en dériver.

    Ainsi, la classe FormeGeometrique pourrait présenter des comportements comme print(), superficie() ou encore perimetre(). Mais tu t'attends à ce que ces comportements s'adaptent au type réel de la forme géométrique : tu t'attends à ce que la fonction print() affiche "rectangle" ou "cercle" ou "triangle" selon le cas, et tu t'attends à ce que les fonctions superficie et perimetre te renvoient une valeur correctement calculée. C'est ce que l'on appelle avoir un "comportement polymorphe" (un comportement qui s'adapte au type réel de l'objet manipulé).

    Pour obtenir un tel comportement, on va déclarer les fonctions print, superficie et perimetre virtual, afin d'indiquer au compilateur que l'on risque de redéfinir le comportement de ces fonctions. Et comme il est impossible de calculer la superficie ou le périmètre d'une forme géométrique dont on ignore tout, nous déclarerons les fonctions perimetre et superficie comme étant virtuelles pures. Cela indique au compilateur que nous ne disposons, au niveau de la classe de base, pas des informations qui permettent de définir un comportement cohérent et que l'on ne définit donc pas le comportement pour ces fonctions.

    Cela va transformer la classe de base en une classe abstraite, qui ne pourra pas être instanciée en tant que telle. Et, pour être en mesure d'instancier les classes dérivées, il faut que les deux fonctions soient correctement définies à chaque fois. au final, nous aurons quelque chose comme
    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    class FormeGeometrique{
        public:
        virtual ~FormeGeometrique(){}
        virtual void print() const{std::cout<<"Forme Geometrique, sans precision"<<std::endl;}
        /* il n'existe aucun comportement "cohérent" pour calculer la superficie d'une forme géométrique
         * dont on ignore tout
         */
        virtual double superficie() const = 0;
     
        /* il n'existe aucun comportement "cohérent" pour calculer le périmètre d'une forme géométrique
         * dont on ignore tout
         */
        virtual double perimetre() const = 0;
    };
    class Cercle : public FormeGeometrique{
        public:
        Cercle(double diametre):diametre_(diametre){}
        virtual void print() const{std::cout<<"Cercle"<<std::endl;}
        virtual double superficie() const{
            return 3.1415926 * diametre_*diametre_/4;
        }
        virtual double perimetre() const{
            return 3.1415926 *diametre_;
        }
        private:
            double diametre_;
    };
    class Rectangle : public FormeGeometrique{
        public:
        Cercle(double hauteur, double largeur):hauteur_(hauteur), largeur_(largeur){}
        virtual void print() const{std::cout<<"Rectangle"<<std::endl;}
        virtual double superficie() const{
            return hauteur_* largeur_;
        }
        virtual double perimetre() const{
            return (hauteur_+largeur_)*2;
        }
        private:
            double hauteur_;
            double largeur_;
    };
    class Triangle : public FormeGeometrique{
        public:
        Cercle(double base, double hauteur):base_(base),hauteur_(hauteur){}
        virtual void print() const{std::cout<<"Triangle"<<std::endl;}
        virtual double superficie() const{
            return hauteur_* largeur_/2;
        }
        virtual double perimetre() const{
            /* ... */
        }
        private:
            double base_;
            double hauteur_;
    };
    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

  19. #19
    Membre du Club
    Homme Profil pro
    touristepationné
    Inscrit en
    Janvier 2012
    Messages
    132
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : touristepationné
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 132
    Points : 57
    Points
    57
    Par défaut
    Super réponses merci!

    Je ne connais pas encore les règles de l'héritage. Est-ce complexe?

  20. #20
    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
    Ce n'est pas complexe, mais elles doivent être appliquées avec la plus grande rigueur.

    La première chose à voir est qu'il faut effectivement pouvoir dire, du pur point de vue du dictionnaire, qu'un objet du type dérivé est "une sorte" d'objet du type de base (ex: une voiture est une sorte de véhicule)

    Une fois cette première étape franchie, il reste la plus importante : respecter les règles de programmation par contrat ;
    1. Les préconditions ne peuvent pas être renforcées dans le type dérivé
    2. les postconditions ne peuvent pas être assouplies dans le type dérivé
    3. Les invariants doivent être respectés

    Il faut considérer tout membre et toute fonction membre (quelle que soit la visibilité) comme étant un invariant.

    Pour ce qui est des pré et postconditions, c'est ce qui t'empêche de faire dériver ListeTriee de Liste ou Carre de Rectangle : il y a des conditions beaucoup plus fortes dans ListeTriee ou dans Carre que dans Liste ou Rectangle : la liste triée doit être triée avant insertion d'un nouvelle élément et doit être triée après, et un carré doit forcément avoir quatre cotés égaux. Liste et Rectangle ne sont pas soumis à ces restrictions
    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

Discussions similaires

  1. Réponses: 2
    Dernier message: 11/08/2009, 10h49
  2. Qu'est-ce que "virtual printer port for usb"
    Par Asdorve dans le forum Autres Logiciels
    Réponses: 2
    Dernier message: 20/07/2006, 13h07

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