--- jupytext: text_representation: extension: .md format_name: myst format_version: 0.13 kernelspec: display_name: C++17 language: C++17 name: xcpp17 rise: auto_select: first autolaunch: false centered: false controls: false enable_chalkboard: true height: 100% margin: 0 maxScale: 1 minScale: 1 scroll: true slideNumber: true start_slideshow_at: selected transition: none width: 90% --- +++ {"slideshow": {"slide_type": "slide"}} # Digressions : surcharge, templates, espaces de noms, ... Nous allons maintenant faire quelques digressions, pour pointer vers des fonctionnalités de C++ que nous avons utilisées sans explications jusqu'ici, et dont l'usage est naturel et potentiellement utile dès maintenant. +++ {"slideshow": {"slide_type": "slide"}, "tags": []} ## Surcharge de fonctions ♣ +++ {"slideshow": {"slide_type": "fragment"}} ### Exemple : la fonction `monMax` +++ {"slideshow": {"slide_type": "skip"}, "tags": []} Nous avons vu maintes fois la fonction `max` sur les entiers : ```{code-cell} --- slideshow: slide_type: fragment tags: [] --- int monMax(int a, int b) { if ( a < b ) return b; else return a; } monMax(1,3) ``` +++ {"slideshow": {"slide_type": "skip"}, "tags": []} On remarquera que le code est générique : on peut par exemple calculer de même le maximum de deux nombres réels : ```{code-cell} --- slideshow: slide_type: fragment tags: [] --- double monMax(double a, double b) { if ( a < b) return b; else return a; } monMax(1.0, 3.5) ``` +++ {"slideshow": {"slide_type": "skip"}, "tags": []} ou même de deux chaînes de caractères : ```{code-cell} --- slideshow: slide_type: fragment tags: [] --- using namespace std; ``` ```{code-cell} :tags: [] string monMax(string a, string b) { if ( a < b) return b; else return a; } monMax("toto", "alfred") ``` +++ {"slideshow": {"slide_type": "fragment"}} :::{hint} Observation Nous avons utilisé chaque fois le même nom de fonction et `C++` a appelé automatiquement la bonne version. ::: +++ {"slideshow": {"slide_type": "fragment"}} :::{hint} Remarque Il serait de même possible d'utiliser le même nom de fonction pour le max à trois arguments (et plus!) : ::: ```{code-cell} :tags: [] int monMax(int a, int b, int c) { return monMax(monMax(a, b), c); } monMax(2,4,3) ``` +++ {"slideshow": {"slide_type": "fragment"}, "tags": []} :::{attention} Attention aux ambiguïtés <br> ::: ```{code-cell} :tags: [] monMax(3, 4.5) ``` +++ {"slideshow": {"slide_type": "slide"}, "tags": []} :::{prf:definition} ***Surcharge de fonction*** - En C++, on peut avoir plusieurs fonctions avec le même nom et des signatures différentes - Idem en Java, mais pas en C ou en Python par exemple! ::: +++ {"slideshow": {"slide_type": "fragment"}, "tags": []} :::{hint} Bonne pratique Il est recommandé que toutes les fonctions ayant le même nom aient la même *sémantique* ::: +++ {"slideshow": {"slide_type": "slide"}, "tags": []} ## Digression : templates ♣ :::{warning} Problème L'exemple précédent n'est pas satisfaisant : on a dû implanter la fonction `monMax` pour chaque type sur lequel on peut faire une comparaison, en dupliquant le même code. ::: +++ {"slideshow": {"slide_type": "fragment"}, "tags": []} :::{hint} Solution Les ******templates****** pour écrire du code *générique* ::: +++ {"slideshow": {"slide_type": "fragment"}, "tags": []} La fonction `monMax` suivante est valide pour tout type sur lequel on peut faire des comparaisons : ```{code-cell} --- slideshow: slide_type: fragment --- template<class T> T monMax(T a,T b) { if ( a < b ) return b; else return a; } ``` ```{code-cell} --- slideshow: slide_type: fragment --- monMax(1,3) ``` ```{code-cell} --- slideshow: slide_type: fragment --- monMax(string("toot"), string("alfred")) ``` ```{code-cell} --- slideshow: slide_type: fragment --- monMax(1.4, 0.5) ``` ```{code-cell} --- slideshow: slide_type: fragment --- monMax(8.0, 4) ``` +++ {"slideshow": {"slide_type": "fragment"}} Les détails seront pour un autre cours! +++ {"slideshow": {"slide_type": "slide"}} ## Digression : espaces de noms ♣ :::{warning} Problème Des milliers de développeurs écrivent des bibliothèques, bibliothèques qui sont par la suite combinées entre elles de multiples façons non anticipées à l'origine. Comment s'assurer qu'il n'y a pas de conflit entre deux fonctions portant le même nom et la même signature dans deux bibliothèques différentes? ::: +++ {"slideshow": {"slide_type": "fragment"}} :::{hint} Solution Isoler chaque bibliothèque dans un ******espace de noms****** ::: +++ {"slideshow": {"slide_type": "fragment"}} :::{prf:example} La bibliothèque standard C++ utilise l'espace de nom `std`. Ainsi, dans le programme suivant, il faudrait en principe mettre `std` devant `cout`, et `endl`. ::: ```{code-cell} --- slideshow: slide_type: fragment --- #include <iostream> int main() { std::cout << "Bonjour!" << std::endl; return 0; } ``` +++ {"slideshow": {"slide_type": "fragment"}} :::{hint} Explication Notre incantation magique : ``` c++ using namespace std; ``` dit simplement de définir des raccourcis pour rendre accessible directement tout ce qui est défini dans l'espace de nom `std`. ::: +++ {"slideshow": {"slide_type": "fragment"}} Vous verrez plus tard comment créer vos propres espaces de noms.