Skip to content
Snippets Groups Projects
Commit 692a5894 authored by Nicolas M. Thiéry's avatar Nicolas M. Thiéry
Browse files

Préparation

parent 8d7ed073
No related branches found
No related tags found
No related merge requests found
No preview for this file type
......@@ -33,30 +33,29 @@ rise:
## Résumé de la séance
**Programmes et compilation :**
:::{admonition} Programmes et compilation
- Algorithme, programme, sources, binaire, assembleur
- Interpréteur, compilateur
- Cycle de vie d'un programme
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Compilation séparée pour la modularité :**
:::{admonition} Compilation séparée pour la modularité
- Découper un programme non seulement en fonctions, mais en fichiers
- Bibliothèque de fonctions réutilisables entre programmes
- Définir des bibliothèque de fonctions réutilisables entre programmes :
- fichier d'entêtes : `max.hpp`
- fichier source : `max.cpp`
- fichier de tests : `maxTest.cpp`
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Digressions :**
:::{admonition} Digressions
- Surcharge : un nom, plusieurs fonctions
- Templates : une fonction, plusieurs types
- Espaces de noms
- Espaces de noms : pour éviter les conflits de noms
:::
+++ {"slideshow": {"slide_type": "slide"}}
......@@ -64,14 +63,14 @@ rise:
+++ {"slideshow": {"slide_type": "fragment"}}
**Développement incrémental :**
:::{hint} Bonne pratique : développement incrémental
- Toujours être «proche de quelque chose qui marche»
- Gestion de version (`git`, `mercurial`, ...)
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Spécifications et tests :**
:::{admonition} Bonnes pratiques : spécifications et tests
- Spécification : définir précisément la sémantique des fonctions :
qu'est-ce qu'elles doivent faire?
......@@ -80,38 +79,39 @@ rise:
+++ {"slideshow": {"slide_type": "fragment"}}
**Modularité :**
:::{hint} Bonne pratique : modularité
- Découpage d'un programme en fonctions : [**cours 4**](../Semaine4/cours.md)
- Découpage d'un programme en modules : **aujourd'hui !**
- Découpage d'un programme en espace de noms : **plus tard**
- Découpage d'un programme en espaces de noms : **plus tard**
:::
+++ {"slideshow": {"slide_type": "slide"}}
### Conclusion : qu'avez-vous vu ce semestre?
### Conclusion : qu'avons nous vu ce semestre?
+++ {"slideshow": {"slide_type": "fragment"}}
**Les bases de la programmation impérative**
:::{admonition} Les bases de la programmation
- Contrôle du flot d'exécution : instructions conditionnelles et itératives, fonctions
- Gestion des données : variables, tableaux, collections, entrées et sorties, fichiers
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Méthodologie de développement**
:::{admonition} Méthodologie de développement
- Développement incrémental
- Spécifications et tests
- Modularité
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Une esquisse de quelques thèmes de l'informatique**
:::{admonition} Une esquisse de quelques thèmes de l'informatique
- Programmation modulaire (S2)
- Algorithmes et structures de données, complexité (S2)
- Science des données (S2)
- Web, graphisme, architecture, réseau, ...
:::
+++ {"slideshow": {"slide_type": "fragment"}}
......
......@@ -29,21 +29,19 @@ rise:
## Revenons à la recette de la mousse au chocolat
**Ingrédients :**
:::{admonition} Ingrédients
:icon: false
250 g de chocolat, 125 g de beurre, 6 œufs, 50 g de sucre, café
:::
**Étapes :**
:::{admonition} Étapes
:icon: false
- Faire fondre le chocolat avec deux cuillères d'eau
- Ajouter le beurre, laisser refroidir puis ajouter les jaunes
- Ajouter le sucre et comme parfum un peu de café
- Battre les blancs jusqu'à former une neige uniforme
- Ajouter au mélange
:::
+++ {"slideshow": {"slide_type": "fragment"}}
......@@ -53,9 +51,11 @@ rise:
Pour répondre à cette question, revenons à la définition :
**Programme** (rappel) : séquence d'**instructions** qui spécifie,
:::{prf:definition} **Programme** (rappel)
Séquence d'**instructions** qui spécifie,
étape par étape, les opérations à effectuer pour obtenir, à partir des
**entrées**, un résultat, la **sortie**.
:::
+++ {"slideshow": {"slide_type": "slide"}}
......@@ -90,12 +90,17 @@ Cela nous amène naturellement à la question suivante :
+++ {"slideshow": {"slide_type": "slide"}}
## Au commencement était l'« assembleur »
## Au commencement était l'assembleur
L'assembleur est le langage que comprend directement l'ordinateur.
:::{prf:definition} Assembleur
L'***assembleur*** est le langage que comprend directement l'ordinateur.
Chaque instruction correspond à une opération élémentaire que peut
effectuer le processeur :
effectuer le processeur.
:::
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
:::{prf:example}
``` nasm
mov -0x1c(%rbp), %edx
mov -0x1c(%rbp), %eax
......@@ -105,12 +110,13 @@ effectuer le processeur :
imul -0x18(%rbp), %eax
mov %eax, -0x14(%rbp)
```
Voyons cet exemple de plus près.
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Exercice :**
Voyons cet exemple de plus près.
:::{exercise}
Exécuter ce fragment d'*assembleur* en suivant les indications
suivantes :
......@@ -122,6 +128,7 @@ suivantes :
- `imul a, b` : multiplier le contenu de a par celui de b et mettre le
résultat dans b
- Initialiser le contenu de la case `%-0x1c(%rbp)` à $3$
:::
+++ {"slideshow": {"slide_type": "fragment"}}
......@@ -139,7 +146,7 @@ bien content de ne pas avoir à programmer tout le temps en assembleur.
**Ce que je veux :**
« Calculer la puissance 4 d'un nombre »
« Calculer la puissance quatrième d'un nombre »
+++ {"slideshow": {"slide_type": "fragment"}}
......@@ -160,7 +167,9 @@ bien content de ne pas avoir à programmer tout le temps en assembleur.
+++ {"slideshow": {"slide_type": "fragment"}}
**Passer de l'un à l'autre ne va pas se faire tout seul**. Il va
falloir un peu de méthode ; c'est le cycle de vie d'un programme.
falloir un peu de méthode.
C'est le **cycle de vie d'un programme**.
+++ {"slideshow": {"slide_type": "slide"}}
......@@ -172,47 +181,48 @@ fonctionnel.
+++ {"slideshow": {"slide_type": "fragment"}}
#### Problème
« Calculer la puissance 4 d'un nombre »
:::{admonition} Problème
« Calculer la puissance quatrième d'un nombre »
:::
+++ {"slideshow": {"slide_type": "fragment"}}
#### Formalisation
:::{admonition} Formalisation
Spécification des **entrées** et des **sorties**
- Spécification des **entrées** et des **sorties**
Scénario d'utilisation : « l'utilisateur rentre au clavier un nombre
entier $x$ ; l'ordinateur affiche en retour la valeur de $x^4$ à l'écran »
- Scénario d'utilisation : « l'utilisateur saisit au clavier un nombre
entier $x$ ; l'ordinateur affiche la valeur de $x^4$ à l'écran »
:::
+++ {"slideshow": {"slide_type": "fragment"}}
#### Recherche d'un algorithme
:::{admonition} Recherche d'un algorithme
- Comment on résout le problème ?
- Quel **traitement** appliquer à l'entrée pour obtenir la sortie
désirée ?
:::
+++ {"slideshow": {"slide_type": "fragment"}}
On note que $x^4=x * x * x * x = (x^2)^2$
Cela nous donne un **algorithme** :
+++ {"slideshow": {"slide_type": "fragment"}}
Cela nous donne un **algorithme** :
- calculer $x*x$
- prendre le résultat et faire de même
+++ {"slideshow": {"slide_type": "slide"}}
#### Digression : La notion d'algorithme
**Définition : Algorithme**
### Digression : La notion d'algorithme
:::{prf:definition} Algorithme
- Description formelle d'un procédé de traitement qui permet, à partir
d'un ensemble d'informations initiales, d'obtenir des informations
déduites
- Succession finie et non ambiguë d'opérations clairement posées
:::
+++ {"slideshow": {"slide_type": "fragment"}}
......@@ -220,7 +230,7 @@ Quelle différence entre un **algorithme** et un **programme** ?
+++ {"slideshow": {"slide_type": "fragment"}}
Un algorithme
Un algorithme:
- doit toujours se terminer !
- est conçu pour communiquer entre humains
- est un concept indépendant du langage dans lequel il est écrit
......@@ -249,7 +259,7 @@ En assembleur ???
+++ {"slideshow": {"slide_type": "fragment"}}
En C++ :
**En C++ :**
Entrée :
......@@ -274,26 +284,26 @@ Sortie :
#### Niveaux de langages de programmation
+++ {"slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
**Langage machine (binaire) :**
Un programme y est directement compréhensible par la machine
+++ {"slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
**Langage d'assemblage (ou assembleur) :**
Un programme y est traduisible mot-à-mot en langage machine
+++ {"slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
**Langage de programmation :**
En général, un programme doit être **transformé** pour être compris
par la machine
+++ {"slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
Comment faire cette transformation ? À la main ?
......@@ -328,10 +338,10 @@ Basic, Javascript, LISP, Perl, Python, C++, ...
**Exemple : compilation en C++ :**
- Programme source : `puissance-quatre.cpp`
- Compilation : `g++ puissance-quatre.cpp -o puissance-quatre`
- Compilation : `clang++ puissance-quatre.cpp -o puissance-quatre`
- Programme objet (ou binaire) : `puissance-quatre`
- Exécution : `./puissance-quatre`
- Fabrication de l'assembleur : `g++ -S puissance-quatre.cpp`
- Fabrication de l'assembleur : `clang++ -S puissance-quatre.cpp`
- Programme en assembleur : `puissance-quatre.s`
+++ {"slideshow": {"slide_type": "fragment"}}
......@@ -357,29 +367,29 @@ ADA, C, C++, FORTRAN, Java, Pascal, ...
### Exécution et mise au point
**Exécuter le programme :**
:::{admonition} Exécuter le programme
- Autant de fois que l'on veut !
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Tester que le programme fonctionne :**
:::{admonition} Tester que le programme fonctionne
- En n'oubliant pas les cas particuliers !!!
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Mise au point :**
:::{admonition} Mise au point
- Correction d'erreurs
- Optimisation du programme (consommation de ressources: temps, mémoire, énergie, ...)
- Optimisation de l'algorithme
- Amélioration du programme (lisibilité, généralisation)
:::
+++ {"slideshow": {"slide_type": "fragment"}}
À chaque fois, on reboucle sur l'étape de compilation, voire de
conception, d'où le terme de cycle de vie.
conception, d'où le terme de **cycle de vie**.
+++ {"slideshow": {"slide_type": "slide"}}
......@@ -391,8 +401,7 @@ s'appuyer sur un peu de
+++ {"slideshow": {"slide_type": "fragment"}}
**Méthodologie :**
:::{admonition} Méthodologie
1. Énoncé du problème
2. Formalisation (quel est le problème précisément ?)
3. Recherche d'un algorithme (comment résoudre le problème ?)
......@@ -400,6 +409,7 @@ s'appuyer sur un peu de
5. Interprétation / Compilation
6. Exécution
7. Mise au point (test, débogage, optimisation, diffusion)
:::
+++ {"slideshow": {"slide_type": "skip"}}
......
......@@ -30,32 +30,27 @@ rise:
# 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 explication
jusqu'ici, et dont l'usage simple est naturel et potentiellement utile
dès maintenant.
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": "fragment"}}
+++ {"slideshow": {"slide_type": "slide"}, "tags": []}
## Surcharge de fonctions ♣
```{code-cell}
---
slideshow:
slide_type: fragment
---
using namespace std;
```
+++ {"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: '-'
slide_type: fragment
tags: []
---
int monMax(int a, int b) {
if ( a < b )
......@@ -63,17 +58,11 @@ int monMax(int a, int b) {
else
return a;
}
```
```{code-cell}
---
slideshow:
slide_type: '-'
---
monMax(1,3)
```
+++ {"slideshow": {"slide_type": "fragment"}}
+++ {"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 :
......@@ -81,7 +70,8 @@ de même le maximum de deux nombres réels :
```{code-cell}
---
slideshow:
slide_type: '-'
slide_type: fragment
tags: []
---
double monMax(double a, double b) {
if ( a < b)
......@@ -89,102 +79,104 @@ double monMax(double a, double b) {
else
return a;
}
```
```{code-cell}
---
slideshow:
slide_type: '-'
---
monMax(1.0, 3.5)
```
+++ {"slideshow": {"slide_type": "fragment"}}
+++ {"slideshow": {"slide_type": "skip"}, "tags": []}
ou même de deux chaînes de caractères :
```{code-cell}
---
slideshow:
slide_type: '-'
slide_type: fragment
tags: []
---
using namespace std;
```
```{code-cell}
:tags: []
string monMax(string a, string b) {
if ( a < b)
return b;
else
return a;
}
```
```{code-cell}
---
slideshow:
slide_type: '-'
---
monMax("toto", "alfred")
```
+++ {"slideshow": {"slide_type": "fragment"}}
Vous remarquerez que l'on a utilisé le même nom de fonction, et que
:::{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}
---
slideshow:
slide_type: '-'
---
:tags: []
int monMax(int a, int b, int c) {
return monMax(monMax(a, b), c);
}
```
```{code-cell}
---
slideshow:
slide_type: '-'
---
monMax(2,4,3)
```
+++ {"slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
Mais attention aux ambiguïtés :
:::{attention} Attention aux ambiguïtés
<br>
:::
```{code-cell}
---
slideshow:
slide_type: '-'
---
:tags: []
monMax(3, 4.5)
```
+++ {"slideshow": {"slide_type": "slide"}}
### Surcharge de fonction : résumé
+++ {"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!
:::
- Il est recommandé que toutes les fonctions ayant le même nom aient
la même *sémantique*
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
+++ {"slideshow": {"slide_type": "fragment"}}
:::{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*
:::
Correctif : 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 :
......@@ -243,27 +235,30 @@ Les détails seront pour un autre cours!
## Digression : espaces de noms ♣
**Problème :**
:::{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
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"}}
**Solution :**
Isoler chaque bibliothèque dans un *espace de noms*.
:::{hint} Solution
Isoler chaque bibliothèque dans un ******espace de noms******
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Exemple :**
:::{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` :
devant `cout`, et `endl`.
:::
```{code-cell}
---
......@@ -279,12 +274,14 @@ int main() {
+++ {"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"}}
......
......@@ -25,7 +25,7 @@ rise:
width: 90%
---
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "f003d1fe379fe84ce034a14aea0c8147", "grade": false, "grade_id": "cell-bc2bac01a1ae5d6e", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
# Modularité, compilation séparée
......@@ -36,40 +36,39 @@ petit bout, d'éviter les redites, etc.
Nous allons de même **découper un programme en plusieurs fichiers**.
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "c32639e12e6a2b647ff43343efe728db", "grade": false, "grade_id": "cell-bc2bac01a1ae5d6f", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
## Compilation séparée
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "9497653142bbd1f090931e2db5641f75", "grade": false, "grade_id": "cell-eda0e2d6022d648b", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
+++ {"slideshow": {"slide_type": "fragment"}}
### Exemple
Considérons les trois programmes suivants :
+++ {"slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
Dans Jupyter :
```{code-cell}
---
slideshow:
slide_type: '-'
---
#include <iostream>
:tags: []
#include "max_simpliste.hpp"
int monMax(int a, int b) {
if ( a >= b )
return a;
else
return b;
}
```
```{code-cell}
monMax(10, 1)
```
+++ {"slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}, "tags": []}
[programme1.cpp](programme1.cpp) : maximum de deux entiers, avec un exemple
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "1492e87493155542d8d49436f01e4b91", "grade": false, "grade_id": "cell-eda0e2d6022d648c", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "-"}}
``` c++
#include <iostream>
using namespace std;
......@@ -80,20 +79,17 @@ int monMax(int a, int b) {
else
return b;
}
```
``` c++
int main() {
cout << monMax(1, 3) << endl;
return 0;
}
```
+++ {"slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}, "tags": []}
[programme2.cpp](programme2.cpp) : maximum de deux entiers, avec interactivité
+++ {"slideshow": {"slide_type": "-"}}
``` c++
#include <iostream>
using namespace std;
......@@ -104,9 +100,7 @@ int monMax(int a, int b) {
else
return b;
}
```
``` c++
int main() {
cout << "Entrez a et b:" << endl;
int a, b;
......@@ -122,7 +116,7 @@ int main() {
On constate une **répétition** : les trois programmes définissent exactement
la même fonction `monMax`, qu'ils utilisent ensuite différemment.
Pourrait-on partager la fonction `monMax` entre ces trois programmes ?
Pourrait-on **partager** la fonction `monMax` entre ces trois programmes ?
C'est ce que nous allons faire en définissant une mini-bibliothèque.
Voyons à quoi cela ressemble.
......@@ -148,7 +142,7 @@ int monMax(int a, int b) {
+++ {"slideshow": {"slide_type": "fragment"}}
Pour utiliser cette bibliothèque, il suffit de l'***inclure*** :
Pour utiliser cette bibliothèque, il suffit de l'******inclure****** :
```{code-cell}
#include "max_simpliste.hpp"
......@@ -160,25 +154,26 @@ monMax(1, 3)
+++ {"slideshow": {"slide_type": "fragment"}}
<div class="alert alert-warning">
:::{attention}
On appelle cela une bibliothèque en ***entêtes seuls*** (***header only***).
On appelle cela une bibliothèque en ******entêtes seuls****** (******header only******).
En `C++`, il y a des cas d'usage où cela peut être pertinent.
Il y a de sérieuses limitations à cette façon de structurer une bibliothèque.
Dans ce cours on évitera.
:::
</div>
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "579b25dc89bdc9c0252cfe90d3f976b0", "grade": false, "grade_id": "cell-04d9ac7b73aa7155", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
#### Exemple : une bibliothèque `max` dans les règles
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "bcc5994c592a52d4141024a74fe4ad11", "grade": false, "grade_id": "cell-04d9ac7b73aa7156", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
+++ {"slideshow": {"slide_type": "fragment"}}
% TODO: ici et dans les pages suivantes: use literalinclude
Contenu du fichier `max.hpp` :
Contenu du fichier [max.hpp](max.hpp) :
``` c++
/** La fonction max
* @param x, y deux entiers
......@@ -190,7 +185,7 @@ int monMax(int a, int b);
+++ {"slideshow": {"slide_type": "fragment"}}
Contenu du fichier `max.cpp` :
Contenu du fichier [max.cpp](max.cpp) :
``` c++
#include "max.hpp"
......@@ -204,10 +199,11 @@ int monMax(int a, int b) {
+++ {"slideshow": {"slide_type": "slide"}}
#### Exemple : deux programmes utilisant la bibliothèque max
#### Exemple : deux programmes utilisant la bibliothèque `max`
+++ {"slideshow": {"slide_type": "fragment"}}
Contenu du fichier [programme1.cpp](programme1.cpp):
``` c++
#include <iostream>
using namespace std;
......@@ -221,6 +217,7 @@ int main() {
+++ {"slideshow": {"slide_type": "fragment"}}
Contenu du fichier [programme2.cpp](programme2.cpp):
``` c++
#include <iostream>
using namespace std;
......@@ -236,13 +233,13 @@ int main() {
}
```
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "4660ee07cdbb406ba256477ea7c4fc59", "grade": false, "grade_id": "cell-c0ee9ca9166c339f", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
#### Exemple : les tests de la bibliothèque `max`
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "12530a4d02fe03e35ea980f1ee58d2b0", "grade": false, "grade_id": "cell-c0ee9ca9166c339g", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
+++ {"slideshow": {"slide_type": "fragment"}}
Contenu du fichier `max-test.cpp` :
Contenu du fichier [max-test.cpp](max-test.cpp) :
``` c++
#include <iostream>
using namespace std;
......@@ -251,8 +248,7 @@ using namespace std;
/** Infrastructure minimale de test **/
#define CHECK(test) if (!(test)) cerr << "Test failed in file " << __FILE__ << " line " << __LINE__ << ": " #test << endl
```
``` c++
void monMaxTest() {
CHECK( monMax(2,3) == 3 );
CHECK( monMax(5,2) == 5 );
......@@ -264,7 +260,7 @@ int main() {
}
```
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "787972a2428cc04cb9217d9a030d58c4", "grade": false, "grade_id": "cell-fdf12d05bb0ffe32", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
### Qu'avons-nous vu ?
......@@ -274,59 +270,63 @@ int main() {
+++ {"slideshow": {"slide_type": "fragment"}}
**Syntaxe :**
:::{admonition} Syntaxe
``` c++
int monMax(int a, int b);
```
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Sémantique :**
- Le programme *définit* quelque part une fonction `monMax` avec cette
*signature* :
:::{admonition} Sémantique
- Le programme ******définit****** quelque part une fonction `monMax` avec cette
******signature****** :
type des paramètres et type du résultat
- Cette définition n'est pas forcément dans le même fichier
- Si cette définition n'existe pas ou n'est pas unique, une erreur est
déclenchée par le compilateur
- Cette erreur est déclenchée au moment où l'on combine les différents
fichiers
Édition de liens; voir plus loin
fichiers: voir plus loin «Édition de liens»
+++ {"slideshow": {"slide_type": "fragment"}}
**♣ Application :**
:::{hint} ♣ Application
Deux fonctions qui s'appellent réciproquement
:::
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "b3709f14a593cf15abcc96057044e99f", "grade": false, "grade_id": "cell-26e5cd21217b8ec5", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
#### Compilation séparée (1)
- Un programme peut être composé de plusieurs ***fichiers source***
Contenu :
- Des *définitions* de fonctions
- Des définitions de fonctions
- Des variables globales, ...
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
- Chaque fichier source est compilé en un ***fichier objet*** (extension : .o)
Contenu :
- Le code binaire des fonctions, ...
- L'*éditeur de liens* combine plusieurs fichiers objet en un
*fichier exécutable*
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
- L'******éditeur de liens****** combine plusieurs fichiers objet en un
******fichier exécutable******
+++ {"slideshow": {"slide_type": "fragment"}}
Voyons cela pour un programme voulant utiliser la bibliothèque `max` :
Les sources sont `max.cpp` et `programme.cpp`.
Les sources sont [max.cpp](max.cpp) et [programme.cpp](programme.cpp).
+++ {"slideshow": {"slide_type": "fragment"}}
On les compile séparément avec :
```shell
g++ -c max.cpp
g++ -c programme.cpp
clang++ -c max.cpp
clang++ -c programme.cpp
```
Cela produit les fichiers objets `max.o` et `programme.o`. Chacun est
......@@ -334,13 +334,17 @@ un bout incomplet de programmes binaires : `max.o` contient le code
binaire de la fonction `max` mais pas la fonction `main`, et
réciproquement pour `programme.o`.
+++ {"slideshow": {"slide_type": "fragment"}}
Il ne reste plus qu'à combiner ces deux bouts de programmes binaires
pour obtenir un programme complet.
```shell
g++ programme.o max.o -o programme
clang++ programme.o max.o -o programme
```
+++ {"slideshow": {"slide_type": "fragment"}}
Maintenant, on peut exécuter le programme obtenu autant de fois qu'on
le souhaite :
......@@ -348,135 +352,138 @@ le souhaite :
./programme
```
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "0d83630ea4ed4d5d557e122d963571f8", "grade": false, "grade_id": "cell-de97499851e34054", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
#### Compilation séparée (2)
**Au moment de l'édition de lien :**
- Chaque fonction utilisée doit être définie une et une seule fois
- La fonction `main` doit être définie une et une seule fois
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "ce17de7f5b94f7bb286b8110e5437571", "grade": false, "grade_id": "cell-de97499851e34055", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
- Chaque fonction utilisée **doit être définie une et une seule fois**
- La fonction `main` **doit être définie une et une seule fois**
**Quelques variantes autour des fichiers objets :**
+++ {"slideshow": {"slide_type": "fragment"}}
:::{hint} ♣ Quelques variantes autour des fichiers objets
- Bibliothèques (.a) :
Une archive contenant plusieurs fichiers objets .o
- Bibliothèques dynamiques (.so) :
Édition de lien dynamique au lancement du programme
:::
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "52664d050cdb13f6a766e3cbcc175719", "grade": false, "grade_id": "cell-e568b9b55cb70a3b", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
#### Fichiers d'entête
:::{prf:definition} Fichier d'entête
Fichier `.hpp` (ou `.h` en C) contenant la *déclaration* des fonctions *définies* dans
le fichier `.cpp` correspondant
:::
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "caf19989e2817546698bf5fbf404d630", "grade": false, "grade_id": "cell-e568b9b55cb70a3c", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
**Exemple :** Fichier d'entête `max.hpp`
+++ {"slideshow": {"slide_type": "fragment"}}
:::{prf:example} Fichier d'entête `max.hpp`
``` c++
int monMax(int a, int b);
```
:::
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "1e9959987853b8d9ed69ad76b649bbe2", "grade": false, "grade_id": "cell-e568b9b55cb70a3d", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
**Syntaxe :** Utilisation d'un fichier d'entête
+++ {"slideshow": {"slide_type": "fragment"}}
#### Utilisation d'un fichier d'entête
:::{admonition} Syntaxe
``` c++
#include "max.hpp"
```
**Sémantique :**
:::
:::{admonition} Sémantique
Utiliser la bibliothèque `max`
:::
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "7c7bbb13cb5d1fe766e13d181ac0e393", "grade": false, "grade_id": "cell-e568b9b55cb70a3e", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
+++ {"slideshow": {"slide_type": "fragment"}}
**Implantation en C++ :**
:::{hint} Implantation en C++
- Équivalent à copier-coller le contenu de `max.hpp` à l'emplacement du
`#include "max.hpp"`
- ♣ Géré par le préprocesseur (cpp)
```
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "ff72d7aa40bd416b2c3dacc17f4839cb", "grade": false, "grade_id": "cell-1501d26cad5b60f2", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
#### Inclusion de fichiers d'entêtes standards
**Syntaxe :**
:::{admonition} Syntaxe
``` c++
#include <iostream>
```
:::
**Sémantique :**
:::{admonition} Sémantique
- Charge la déclaration de toutes les fonctions définies dans la
bibliothèque standard `iostream` de C++
- Le fichier `iostream` est recherché dans les répertoires standards
du système
- Sous linux : `/usr/include`, ...
:::
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "eeb3f33e690b970c5a4138874c58ed52", "grade": false, "grade_id": "cell-208ec2ed61304261", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "skip"}, "tags": []}
## Résumé
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "84c2764e1ac634a4c126e1fb2c9ed6f8", "grade": false, "grade_id": "cell-208ec2ed61304262", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
+++ {"slideshow": {"slide_type": "slide"}, "tags": []}
### Résumé : implantation d'une bibliothèque en C++
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "d26c3cdec520f8f76b0624b17f950fe6", "grade": false, "grade_id": "cell-208ec2ed61304263", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
**Écrire un fichier d'entête (max.hpp) :**
+++ {"slideshow": {"slide_type": "fragment"}}
:::{admonition} Écrire un fichier d'entête (max.hpp)
- La déclaration de toutes les fonctions publiques
- *Avec leur documentation !*
:::
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "9b390f6d19d63b7222aaf3e9ea2c2733", "grade": false, "grade_id": "cell-208ec2ed61304264", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
**Écrire un fichier source (max.cpp) :**
+++ {"slideshow": {"slide_type": "fragment"}}
:::{admonition} Écrire un fichier source (max.cpp)
- La définition de toutes les fonctions
- *Inclure le fichier .hpp !*
:::
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "b16ddc2f444fbd91507b32f1ad2bb135", "grade": false, "grade_id": "cell-208ec2ed61304265", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
**Écrire un fichier de tests (maxTest.cpp) :**
+++ {"slideshow": {"slide_type": "fragment"}}
:::{admonition} Écrire un fichier de tests (maxTest.cpp)
- Les fonctions de tests
- Une fonction `main` lançant tous les tests
:::
+++ {"slideshow": {"slide_type": "slide"}}
### Résumé : utilisation d'une bibliothèque en C++
**Inclusion des entêtes :**
:::{admonition} Inclusion des entêtes
```c++
#include <iostream> // fichier d'entête standard
#include "max.hpp" // fichier d'entête perso
```
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Compilation :**
:::{admonition} Compilation
```shell
g++ -c max.cpp
g++ -c programme1.cpp
g++ max.o programme1.o -o programme1
clang++ -c max.cpp
clang++ -c programme1.cpp
clang++ max.o programme1.o -o programme1
```
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**En une seule étape :**
:::{admonition} En une seule étape
```shell
g++ max.cpp programme1.cpp -o programme1
clang++ max.cpp programme1.cpp -o programme1
```
:::
+++ {"slideshow": {"slide_type": "skip"}, "tags": []}
## Suite
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment