Reprenons le projet Peinture du cours Première Notion.
Rappelons que ce programme permet de calculer la surface à peindre d'une pièce rectangulaire connaissant les dimensions de la pièce (longueur, largeur), le nombre de fenêtres et le nombres de portes.
Cet exemple nous avait justement servi à illustrer le principe du découpage d'un traitement en sous-traitements. Lorsqu'un calcul est trop complexe, on a intérêt à le découper en plusieurs calculs intermédiaires et sauvegarder les résultats intermédiaires dans des variables.
Cela nous avait donné le code suivant:
int main(int argc, char** argv) { // Lecture des données cout << "Largeur de la piece :"; cin >> LargeurPiece; cout << "Longueur de la piece :"; cin >> LongueurPiece; cout << "Nombre de fenetres :"; cin >> NFenetre; cout << "Nombre de portes :"; cin >> NPorte; // Calcul de la surface des murs SurfaceDesMurs = 2 * (LargeurPiece * HAUTEUR_MUR + LongueurPiece * HAUTEUR_MUR); // Calcul de la surface des fenetres SurfaceDesFenetres = NFenetre * LARGEUR_FENETRE * HAUTEUR_FENETRE; // Calcul de la surface des portes SurfaceDesPortes = NPorte * LARGEUR_PORTE * HAUTEUR_PORTE; // Calcul de la surface à peindre SurfacePeinture = SurfaceDesMurs - SurfaceDesFenetres - SurfaceDesPortes; // Affichage du résultat cout << "Surface a peindre :" << SurfacePeinture; return 0; }
Nous avons ici un exemple de code qui peut très facilement se réécrire à l'aide de sous-programmes de la manière suivante:
int main(int argc, char** argv) { // Lecture des données cout << "Largeur de la piece :"; cin >> LargeurPiece; cout << "Longueur de la piece :"; cin >> LongueurPiece; cout << "Nombre de fenetres :"; cin >> NFenetre; cout << "Nombre de portes :"; cin >> NPorte; // Traitement des données CalculerSurfaceDesMurs (); CalculerSurfaceDesFenetres (); CalculerSurfaceDesPortes (); CalculerSurface_A_Peindre (); // Affichage du résultat cout << "Surface a peindre :" << SurfacePeinture; return 0; }
Les instructions en blanc sont des appels de sous-programme.
Comparez ce code à celui de la version précédente: il est devenu plus court et plus lisible.
Les instructions permettant de calculer les surfaces (murs, fenêtres, portes, surface à peindre) sont à présent contenues dans des sous-programmes situés avant le programme principal, juste après la déclaration des variables. Voici leur code:
.... void CalculerSurfaceDesMurs () { SurfaceDesMurs = 2 * (LargeurPiece * HAUTEUR_MUR + LongueurPiece * HAUTEUR_MUR); } void CalculerSurfaceDesFenetres () { SurfaceDesFenetres = NFenetre * LARGEUR_FENETRE * HAUTEUR_FENETRE; } void CalculerSurfaceDesPortes () { SurfaceDesPortes = NPorte * LARGEUR_PORTE * HAUTEUR_PORTE; } void CalculerSurface_A_Peindre () { SurfacePeinture = SurfaceDesMurs - SurfaceDesFenetres - SurfaceDesPortes; } ....
Nous avons ici quatre déclaration de sous-programmes. Tout comme le programme principal, chaque déclaration de sous-programme est composée d'une entête (ligne en bleu) et d'un corps (lignes en blanc).
Précisons également que les quatre exemples de sous-programmes présentés ici sont très particuliers. Tout d'abord, ils n'ont pas de paramètres (la notion de paramètre d'un sous-programme sera abordé ultérieurement) et deuxièmement ce sont tous des procédures. En effet, nous verrons plus loin dans le cours qu'il existe deux catégories de sous-programmes: les procédures et les fonctions. Tous les sous-programmes de notre exemple sont des procédures sans paramètres.
Un sous-programme ne s'éxécute que lorsqu'il est appelé. Pour une procédure, cela signifie qu'il existe quelque part dans le code une instruction d'appel de ce sous-programme. Dans notre exemple, ce sont les quatre instructions en blanc dans le corps du programme principal.
Voyons un peu comment s'exécute le programme.
L'exécution d'un programme C++ démarre toujours à la première instruction du programme principal.
Dans notre exemple, ce sera l'instruction:
cout << "Largeur de la piece :";
Après avoir exécuté les instructions de lectures des données, l'ordinateur rencontre une instruction d'appel du sous-programme CalculerSurfaceDesMurs.
Cet appel va déclencher l'exécution de ce sous-programme. C'est à dire que l'ordinateur va à présent exécuter les instructions se trouvant à l'intérieur du corps du sous-programme CalculerSurfaceDesMurs. En l'occurence, il s'agit de l'instruction:
SurfaceDesMurs = 2 * (LargeurPiece * HAUTEUR_MUR + LongueurPiece * HAUTEUR_MUR);
Lorsque l'exécution de cette procédure est terminée, il y a un retour de sous-programme , c'est à dire que l'exécution continue à l'instruction qui suit l'appel du sous-programme venant d'être appelé. Dans notre cas, le retour se fait donc à l'instruction d'appel du sous-programme CalculerSurfaceDesFenetres.
Ce sous-programme sera donc exécuté et au retour, ce sera l'appel du sous-programme CalculerSurfaceDesFenetres, etc ... jusqu'à ce que tous les appels de sous-programme contenu dans le corps du programme principal soient exécutés. Et finalement, l'exécution du programme se terminera par l'affichage du résultat.
Le mécanisme de retour de sous-programme que nous avons décrit ici s'applique à tous les appels de procédure: après l'exécution d'une procédure, l'ordinateur revient automatiquement à l'instruction qui suit l'appel. Pour les fonctions, nous verrons que le mécanisme de retour est légèrement différent.