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 :

Les fonctions virtuelles


Sujet :

C++

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 11
    Points : 9
    Points
    9
    Par défaut Les fonctions virtuelles
    Bonjour

    A quoi sert la fonction virtuelle ?

  2. #2
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  3. #3
    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 gros, une fonction virtuelle indique au compilateur
    je vais définir un comportement particulier pour cette fonction, adapté pour le type que je suis occupé à définir, mais, si quelqu'un définit un type qui hérite de mon type particulier, il pourra décider de redéfinir ce comportement s'il je juge utile.
    Ce genre de fonction permet de définir ce que l'on appelle des comportements polymorphes quand on a besoin de classes substituables aux termes du principe de substituabilité de Liskov.

    Un comportement polymorphe est un comportement susceptible de s'adapter aux circonstances lorsqu'il est invoqué.

    Le fait que tu aies un menu contextuel différent quand tu en demande l'affichage sur différents élément (par exemple: un élément qui se trouve sur le bureau ou sur la barre de tache de ton système d'exploitation) peut être considéré comme étant un comportement polymorphe : c'est toujours un menu contextuel, il te permet toujours d'accéder à différentes actions, mais les actions auxquelles il te donnent accès sont adaptées en fonction des circonstances.

    Le polymorphisme -- la capacité d'un comportement à s'adapter aux circonstances -- peut être classé en trois catégories distinctes : Le polymorphisme ad-hoc, le polymorphisme paramétrique (spécifique à C++) et le polymorphisme universel.

    Le polymorphisme ad-hoc est lui-même séparé en deux catégories:
    1. La coercition qui est la capacité de certains types à être convertis en d'autres de manière plus ou moins implicite et
    2. La surcharge qui est la possibilité dont dispose le développeur de définir deux fonctions qui portent le même nom mais qui prennent des arguments dont le type est différents (et dont le comportement sera similaire)

    Le polymorphisme paramétrique est la capacité d'un comportement à s'adapter au type de l'objet sur lequel il est invoqué en utilisant le paradigme générique "je ne sais pas quel type d'objet j'utilise, mais je sais comment je vais l'utiliser".

    Enfin, le polymorphisme universel, celui qui est autorisé par les fonctions virtuelles, s'appelle aussi le polymorphisme d'inclusion.

    Le principe est de se dire : je crée un type de base (FormeGeométrique, par exemple), qui doit exposer un comportement ("Dessines-toi", par exemple). Ce comportement devra être différent pour un cercle que pour un carré, qui sont tous les deux des FormesGéométriques.

    On en arrive donc à définir une classe FormeGeometrique qui pourrait ressembler à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class FormeGeometrique{
        public:
            virtual void dessineToi() const{
                std::cout<<"je suis une forme géométrique"<<std::endl;
             }
    };
    La fonction dessineToi pourrait ne rien faire, car on ne sait, a priori, pas comment dessiner une forme géométrique dont on ignore tout (on pourrait aussi déclarer cette fonction comme "virtuelle pure" afin d'indiquer au compilateur qu'on est dans l'incapacité de définir le comportement en question)

    On ferait alors hériter publiquement la classe Cercle de FormeGeometrique, parce qu'un cercle est bel et bien une forme géométrique. Et nous comme savons comment demander au cercle de se tracer, nous pouvons redéfinir la fonction dessinesToi pour le cercle.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Cercle :FormeGeometrique{
        public:
            virtual void dessineToi() cons{
                std::cout<<"je suis un cercle"<<std::endl;
             }
     
    };
    Et nous pourrions faire de même avec la classe Carre, pour les mêmes raisons:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Carre :FormeGeometrique{
        public:
            virtual void dessineToi() const{
                std::cout<<"je suis un carré"<<std::endl;
             }
     
    };
    A partir de là, nous pouvons envisager de créer une collection de "formes géométriques" -- sans précision -- qui contiendrait plusieurs carré et plusieurs cercles, sous une forme proche de (C++11 inside)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int main(){
        std::vector<std::unique_ptr<FormeGeometrique> tab;
        tab.emplace_back(std::unique_ptr<FormeGeometrique>(new Cercle));
        tab.emplace_back(std::unique_ptr<FormeGeometrique>(new Carre));
        tab.emplace_back(std::unique_ptr<FormeGeometrique>(new Cercle));
        tab.emplace_back(std::unique_ptr<FormeGeometrique>(new Carre));
        tab.emplace_back(std::unique_ptr<FormeGeometrique>(new Cercle));
        return 0;
    }
    Tu remarqueras que j'ai alors dans tab trois cercles et deux carrés. Si nous décidons d parcourir tous les éléments de tab et de leur demander de s'afficher, sous une forme proche de (C++11 inside)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int main(){
        std::vector<std::unique_ptr<FormeGeometrique> tab;
        tab.emplace_back(std::unique_ptr<FormeGeometrique>(new Cercle));
        tab.emplace_back(std::unique_ptr<FormeGeometrique>(new Carre));
        tab.emplace_back(std::unique_ptr<FormeGeometrique>(new Cercle));
        tab.emplace_back(std::unique_ptr<FormeGeometrique>(new Carre));
        tab.emplace_back(std::unique_ptr<FormeGeometrique>(new Cercle));
        for(auto const & it : tab){
            it.get()->dessinesToi();
        }
        return 0;
    }
    Nous pourrons remarquer que le comportement observé se sera bel et bien adapté au type de l'objet réel (carré ou cercle) car le premier, le troisième et le cinquième élément afficheront "je suis un cercle" alors que le deuxième et le quatrième afficheront "je suis un carré".

    Voilà ce qu'est une fonction virtuelle, et voilà à quoi elle sert
    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

  4. #4
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    On ne va pas être d'accord ici. Pour commencer la classification classique (celle de Cardelli et Wargner dans On Understanding Types), c'est

    * polymorphisme ad-hoc, càd nécessitant une définition pour chaque variante, est bien subdivisé en coercition et surcharge,

    * polymorphisme universel, càd capable de traiter une infinité de types, est subdivisé en paramétrique (qui n'est pas propre au C++, il est présent en Ada, Eiffel et surtout dans les langages fonctionnels où polymorphisme signifie souvent polymorphisme paramétrique), et d'inclusion qui est qu'une valeur peut être de plusieurs types.

    Mais où je ne suis pas du tout d'accord, c'est que le polymorphisme d'inclusion c'est les fonctions virtuelles. Les fonctions virtuelles c'est un type de surcharge, résolue dynamiquement, mais ce n'est "que" de la surcharge. En C++, le principal effet du polymorphisme d'inclusion, c'est le fait que
    le type statique peut être différent du type dynamique, qu'un pointeur ou une référence peut désigner des objets de type différent (n'importe quelle type dérivé de la classe de base).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  5. #5
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Salut

    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Mais où je ne suis pas du tout d'accord, c'est que le polymorphisme d'inclusion c'est les fonctions virtuelles. Les fonctions virtuelles c'est un type de surcharge, résolue dynamiquement, mais ce n'est "que" de la surcharge. En C++, le principal effet du polymorphisme d'inclusion, c'est le fait que
    le type statique peut être différent du type dynamique, qu'un pointeur ou une référence peut désigner des objets de type différent (n'importe quelle type dérivé de la classe de base).
    C'est vrai, mais les fonctions virtuelles ne peuvent être exploitées qu'en utilisant le polymorphisme d'inclusion, même si elles ne sont pas sa seule propriété, on peut comprendre le raccourci emprunté par Koala.
    Find me on github

  6. #6
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    C'est vrai, mais les fonctions virtuelles ne peuvent être exploitées qu'en utilisant le polymorphisme d'inclusion, même si elles ne sont pas sa seule propriété, on peut comprendre le raccourci emprunté par Koala.
    Je n'arrive pas a voir dans ce que tu appelles un raccourci autre chose que de la confusion. Si je vois un interet a une presentation de ce que sont les fonctions virtuelles qui ne fait pas appel a une classification des types de polymorphismes (l'interet principal d'une telle classification n'est perceptible qu'apres avoir ete exposes a ces differentes types, de preference dans differents langages -- bien que le C++ qui dispose des quatres types avec trois mecanismes differents de surcharge soit probablement le langage qui permet d'aborder le plus facilement la classification complete), je ne vois aucun interet a presenter une telle classification pour ensuite ne pas placer les fonctions virtuelles a leur place dedans.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

Discussions similaires

  1. Question sur les fonctions virtuelles
    Par beegees dans le forum C++
    Réponses: 9
    Dernier message: 13/04/2008, 19h54
  2. Bug sur les fonctions virtuelles
    Par Anthony.Desvernois dans le forum C++
    Réponses: 4
    Dernier message: 28/01/2008, 17h30
  3. Réponses: 2
    Dernier message: 07/10/2004, 17h00

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