Bonjour
A quoi sert la fonction virtuelle ?
Bonjour
A quoi sert la fonction virtuelle ?
"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)
Salut,
En gros, une fonction virtuelle indique au compilateurCe 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.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.
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:
- La coercition qui est la capacité de certains types à être convertis en d'autres de manière plus ou moins implicite et
- 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 à
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)
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; } };
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.
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 Cercle :FormeGeometrique{ public: virtual void dessineToi() cons{ std::cout<<"je suis un cercle"<<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 class Carre :FormeGeometrique{ public: virtual void dessineToi() const{ std::cout<<"je suis un carré"<<std::endl; } };
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 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; }
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é".
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; }
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
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.
Find me on github
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.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager