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).
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.
Partager