Aller au contenu
Topos Uranos

Résumé

Jusqu’ici, chaque programme du cours a été un seul bloc, main, dans lequel tout s’écrit là où on l’utilise. Cette leçon enseigne à donner un nom à une partie d’un programme et à l’utiliser sans regarder son intérieur : la fonction. On y étudie la déclaration, qui annonce au compilateur le nom, le type de retour et les paramètres ; la définition, qui ajoute le corps ; et l’appel, qui transfère le contrôle à ce corps et reçoit la valeur renvoyée. On y distingue ce que le compilateur vérifie à la compilation (que chaque appel concorde avec une déclaration) de ce qui se passe à l’exécution (le saut vers la définition et le retour). On y explique pourquoi atteindre la fin d’une fonction qui doit renvoyer une valeur sans passer par un return est un comportement indéfini. On y suit l’exécution avec la pile d’appels, qui garde un cadre pour chaque appel en cours. Et on y spécifie chaque fonction par un contrat, sa précondition et sa postcondition, qui dit ce que la fonction exige de l’appelant et ce qu’elle garantit en échange.

Objectifs d’apprentissage

  1. Déclarer, définir et appeler des fonctions avec des paramètres et une valeur de retour, et indiquer dans un programme quelle partie est la déclaration et laquelle est la définition.
  2. Suivre avec un diagramme de la pile d’appels l’exécution d’un programme dont les fonctions s’appellent entre elles.
  3. Spécifier une fonction par sa précondition et sa postcondition, et écrire un appel qui viole la précondition.
  4. Expliquer pourquoi une fonction qui ne renvoie pas de valeur sur un certain chemin est un comportement indéfini, et reconnaître l’avertissement correspondant du compilateur.

Pourquoi des fonctions

Les programmes de l’unité précédente résolvaient chaque problème à l’intérieur de main, et cela a suffi tant que les problèmes étaient petits. Or, dès qu’un programme grandit, trois difficultés apparaissent. La première est la répétition : si le même calcul est nécessaire en trois endroits, on l’écrit trois fois, et une erreur qu’il contient se corrige trois fois (ou bien on oublie de la corriger à l’un des endroits). La deuxième est la lecture : un bloc de cinquante lignes ne dit pas ce qu’il fait, mais comment il le fait, et le lecteur doit reconstruire l’intention à partir du mécanisme. La troisième est le test : si tout est mélangé, il n’y a aucun moyen de vérifier une partie sans exécuter le reste.

Une fonction est un fragment de programme doté d’un nom, qui reçoit des données, appelées paramètres, et livre un résultat, appelé valeur de retour. Les mathématiques connaissent l’idée depuis des siècles : la distance entre deux points du plan est une fonction de leurs quatre coordonnées, d(x1,y1,x2,y2)=(x2−x1)2+(y2−y1)2d(x_1, y_1, x_2, y_2) = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}, et celui qui calcule le périmètre d’un triangle ne répète pas la formule trois fois, mais la nomme et l’applique trois fois. En C++, on écrit la même chose.

ExempleLe périmètre d’un triangle

Le programme lit les coordonnées des trois sommets d’un triangle et écrit son périmètre, qui est la somme des longueurs de ses trois côtés.

Programme en C++
#include <cmath>#include <iostream>#include <print>​// Distance entre les points (x1, y1) et (x2, y2).double distance(double x1, double y1, double x2, double y2){    const double dx{x2 - x1};    const double dy{y2 - y1};    return std::sqrt(dx * dx + dy * dy);}​int main(){    double ax{};    double ay{};    double bx{};    double by{};    double cx{};    double cy{};    std::cin >> ax >> ay >> bx >> by >> cx >> cy;    const double perimeter{distance(ax, ay, bx, by) + distance(bx, by, cx, cy)                           + distance(cx, cy, ax, ay)};    std::println("Périmètre : {}", perimeter);}
Entrée du programme
0 0 3 0 0 4
Sortie
Périmètre : 12

Les côtés du triangle de sommets (0,0)(0, 0), (3,0)(3, 0) et (0,4)(0, 4) mesurent 3, 5 et 4, et leur somme vaut 12.

La fonction distance s’écrit une fois et s’utilise trois fois ; main se lit comme la définition du périmètre, « la somme de trois distances » ; et distance peut être testée seule, avec un couple de points dont on connaît la distance. On gagne ainsi les trois choses qui manquaient. La morale générale, qui vaut dans tout langage, est qu’une fonction nomme une idée : celui qui l’utilise pense à ce qu’elle fait, non à la manière dont elle le fait. Cette séparation entre l’usage et la réalisation s’appelle abstraction procédurale, et c’est le thème de toute l’unité.