Appel et déclaration de sous-programme


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;
}            

Appel de sous-programmes

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.

Déclaration de sous-programme

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.

Exécution et retour d'un sous-programme. Cas particulier des procédures

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.