Skip to content
Snippets Groups Projects
cours-digressions.md 5.43 KiB
Newer Older
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
---
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
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
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.
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed

Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
+++ {"slideshow": {"slide_type": "slide"}, "tags": []}
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed

## Surcharge de fonctions ♣

+++ {"slideshow": {"slide_type": "fragment"}}

### Exemple : la fonction `monMax`

Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
+++ {"slideshow": {"slide_type": "skip"}, "tags": []}

Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
Nous avons vu maintes fois la fonction `max` sur les entiers :

```{code-cell}
---
slideshow:
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
  slide_type: fragment
tags: []
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
---
int monMax(int a, int b) {
    if ( a < b )
        return b;
    else
        return a;
}

monMax(1,3)
```

Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
+++ {"slideshow": {"slide_type": "skip"}, "tags": []}
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed

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:
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
  slide_type: fragment
tags: []
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
---
double monMax(double a, double b) {
    if ( a < b)
        return b;
    else
        return a;
}

monMax(1.0, 3.5)
```

Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
+++ {"slideshow": {"slide_type": "skip"}, "tags": []}
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed

ou même de deux chaînes de caractères :

```{code-cell}
---
slideshow:
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
  slide_type: fragment
tags: []
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
---
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
using namespace std;
```

```{code-cell}
:tags: []

Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
string monMax(string a, string b) {
    if ( a < b)
        return b;
    else
        return a;
}

monMax("toto", "alfred")
```

+++ {"slideshow": {"slide_type": "fragment"}}

Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:::{hint} Observation
Nous avons utilisé chaque fois le même nom de fonction et
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
`C++` a appelé automatiquement la bonne version.
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:::
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed

+++ {"slideshow": {"slide_type": "fragment"}}

Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:::{hint} Remarque
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
Il serait de même possible d'utiliser le même nom de fonction pour le
max à trois arguments (et plus!) :
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:::
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed

```{code-cell}
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:tags: []

Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
int monMax(int a, int b, int c) {
    return monMax(monMax(a, b), c);
}

monMax(2,4,3)
```

Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:::{attention} Attention aux ambiguïtés
<br>
:::
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed

```{code-cell}
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:tags: []

Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
monMax(3, 4.5)
```

Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
+++ {"slideshow": {"slide_type": "slide"}, "tags": []}
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:::{prf:definition} ***Surcharge de fonction***
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
-   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!
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:::
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:::{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": []}
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed

## Digression : templates ♣

Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:::{warning} Problème
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
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.
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:::

+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}

:::{hint} Solution
Les ******templates****** pour écrire du code *générique*
:::
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed

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
---
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
using namespace std;
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
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 ♣

Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:::{warning} Problème
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed

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
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
anticipées à l'origine.

Comment s'assurer qu'il n'y a pas de conflit
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
entre deux fonctions portant le même nom et la même signature dans
deux bibliothèques différentes?
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:::
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed

+++ {"slideshow": {"slide_type": "fragment"}}

Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:::{hint} Solution
Isoler chaque bibliothèque dans un ******espace de noms******
:::
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed

+++ {"slideshow": {"slide_type": "fragment"}}

Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:::{prf:example}
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
La bibliothèque standard C++ utilise l'espace de nom `std`. Ainsi,
dans le programme suivant, il faudrait en principe mettre `std`
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
devant `cout`, et `endl`.
:::
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed

```{code-cell}
---
slideshow:
  slide_type: fragment
---
#include <iostream>
int main() {
    std::cout << "Bonjour!" << std::endl;
    return 0;
}
```

+++ {"slideshow": {"slide_type": "fragment"}}

Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:::{hint} Explication
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
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`.
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
:::
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed

+++ {"slideshow": {"slide_type": "fragment"}}

Vous verrez plus tard comment créer vos propres espaces de noms.