Fabio [email protected]
Programmation Orientée Objet en C++Programmation Orientée Objet en C++
4ème Partie: Fonctions4ème Partie: Fonctions
© 1997-2003 Fabio HERNANDEZ108POO en C++: Fonctions
Vue d'EnsembleVue d'Ensemble
Notions de base Types, variables, opérateursContrôle d'exécutionFonctionsMémoire dynamiqueQualité du logicielEvolution du modèle objet Objets et classesFonctions membresClasses génériquesHéritagePolymorphismeHéritage multipleEntrée/sortie
© 1997-2003 Fabio HERNANDEZ109POO en C++: Fonctions
Table des MatièresTable des Matières
Déclaration de la FonctionUtilisation de la FonctionPrototype de FonctionContrôle de TypeValeur de RetourSignature de FonctionPassage des ArgumentsTableau comme ArgumentFonctions InlinePortée des VariablesDurée de Vie des Variables
© 1997-2003 Fabio HERNANDEZ110POO en C++: Fonctions
Déclaration de la FonctionDéclaration de la Fonction
Une fonction est une opération définie par le programmeurLes opérandes sont les paramètres de la fonctionExemple
int min(int a, int b){
return (a < b) ? a : b;}
type de lavaleur deretour
liste des paramètres
corps dela fonction
nom de lafonction
© 1997-2003 Fabio HERNANDEZ111POO en C++: Fonctions
Utilisation de la FonctionUtilisation de la Fonction
Toute fonction doit être déclarée avant son utilisation
#include <iostream> // C++ standard I/O declarations
extern int min(int a, int b);
int main(){
int value1;int value2;cout << "Enter two integers: " << endl;cin >> value1 >> value2;cout << "The minimun between: " << value1
<< " and " << value2 << " is " << min(value1, value2) << endl;
return 0;}
© 1997-2003 Fabio HERNANDEZ112POO en C++: Fonctions
Prototype de FonctionPrototype de Fonction
Une fonction ne peut être définie qu'une seule fois dans un programmeMais peut être utilisée autant de fois que nécessaireGénéralement, elle est définie dans un fichier .cpp avec d'autres fonctions et utilisée dans des modules différentsLe moyen de déclarer une fonction est le prototype
extern int min(int a, int b);
L'objectif du prototype est d'informer le compilateur du type de la valeur de retour, du nombre de paramètres et du type de chacun
© 1997-2003 Fabio HERNANDEZ113POO en C++: Fonctions
Prototype de Fonction (suite)Prototype de Fonction (suite)
Associé à chaque module (fichier .cpp) il faut créer un fichier avec les prototypes des fonctions définies dans celui-ciCe fichier de prototypes sera inclus via une instruction pré-processeur dans tous les autres modules qui utilisent une ou plusieurs de ces fonctionsExemple: supposons que dans le fichier util.cpp se trouvent les définitions des fonctions min et abs suivantes
int min(int a, int b){
return (a < b) ? a : b;}
int abs(int a){
return (a < 0) ? -a : a;}
© 1997-2003 Fabio HERNANDEZ114POO en C++: Fonctions
Prototype de Fonction (suite)Prototype de Fonction (suite)
Nous créons le fichier util.prt (le nom n'a pas d'importance pour le compilateur mais en a pour le programmeur) avec les déclarations suivantes
extern int min(int a, int b);extern int abs(int a);
Ce fichier peut maintenant être inclus dans tout module (fichier.cpp) nécessitant une des fonctions définies dans util.cpp
#include <iostream>#include "util.prt"int main(){
cout << "The absolute value of -345 is: "<< abs(-345) << endl;
return 0; }
© 1997-2003 Fabio HERNANDEZ115POO en C++: Fonctions
Contrôle de TypeContrôle de Type
C++ est un langage fortement typéLe type de la valeur de retour et de chacun des arguments d'une fonction sont contrôlés en compilationS'il y a des différences entre le type de la déclaration et le type des arguments utilisés dans l'invocation de la fonction
une conversion implicite est effectuée si possible (probablement avec warning)
int i = min(234, 78.90); // conversion a int 78
autrement, une erreur est détectée et la compilation échoueint i = min(234, "a string"); // ERROR
Le nombre d'arguments est aussi contrôlé
© 1997-2003 Fabio HERNANDEZ116POO en C++: Fonctions
Valeur de RetourValeur de Retour
Peut être d'un type fondamental (int, long,...), d'un type dérivé (int*) ou d' un type défini par le programmeur
enum Color {Black, White};Color getComplementaryColor(Color currentColor){
return (currentColor == Black) ? White : Black;}
Le type void est utilisé pour signifier l'absence de valeur de retourvoid printError(const char* message){
cerr << "ERROR: " << message << endl;}
L'instruction return n'est pas strictement nécessaire pour une fonction qui retourne void
© 1997-2003 Fabio HERNANDEZ117POO en C++: Fonctions
Signature de FonctionSignature de Fonction
La liste des arguments de la fonction est connue comme la signature de la fonctionLe nom et la signature de la fonction identifient pleinement chaque fonctionExemple:
float min(float a, float b){
return (a < b) ? a : b;}
est différente de la fonction min vue précédemment
© 1997-2003 Fabio HERNANDEZ118POO en C++: Fonctions
Signature de Fonction (suite)Signature de Fonction (suite)
Lors de l'invocation de la fonction, le compilateur choisit entre les différentes possibilités, selon le type des arguments
extern float min(float a, float b);extern int min(int a, int b);void main(){
const float f1 = 0.234;const float f2 = 34.90;const int i1 = 190;int intMin = min(i1, 250);
// min(int, int) is calledfloat floatMin = min(f1, f2);
// min(float, float) is called}
© 1997-2003 Fabio HERNANDEZ119POO en C++: Fonctions
Signature de Fonction (suite)Signature de Fonction (suite)
Le type de la valeur de retour ne fait pas partie de la signature
int min(short a, short b);
short min(short a, short b);
// ERROR: same name and signature
© 1997-2003 Fabio HERNANDEZ120POO en C++: Fonctions
Passage des ArgumentsPassage des Arguments
Les arguments des fonctions en C++ sont passés par valeurUne copie de la valeur de chaque argument est copiée dans la pile d'exécution de la fonctionLes modifications faites à ces valeurs affectent uniquement les copies et ne sont pas reflétées dans les arguments actuelsExemple: soit la fonction
void increment(int value){
value += 1;}
© 1997-2003 Fabio HERNANDEZ121POO en C++: Fonctions
Passage des Arguments (suite)Passage des Arguments (suite)
extern increment(int i);void main(){
int counter=100;cout << "Before increment, counter is = "
<< counter << endl;increment(counter);cout << "After increment, counter is = "
<< counter << endl;}
produitBefore increment, counter is = 100After increment, counter is = 100
© 1997-2003 Fabio HERNANDEZ122POO en C++: Fonctions
Passage des Arguments (suite) Passage des Arguments (suite)
Le passage des arguments par valeur n'est pas toujours souhaitable
quand la fonction doit changer la valeur des argumentsquand l'argument de la fonction est un objet de grande taille: le coût en temps et en mémoire de la copie serait très élevé
Deux façons de passer les arguments par référenceutilisation des pointeurs
void increment(int* value){
*value += 1;}
à l'invocation, l'argument de la fonction est l'adresse de l'objet et pas l'objet lui même
© 1997-2003 Fabio HERNANDEZ123POO en C++: Fonctions
Passage des Arguments (suite)Passage des Arguments (suite)
extern increment(int* value);void main(){
int counter=100;cout << "Before increment, counter is = "
<< counter << endl;increment(&counter); // pass the address of countcout << "After increment, counter is = "
<< counter << endl;}
produitBefore increment, counter is = 100After increment, counter is = 101
© 1997-2003 Fabio HERNANDEZ124POO en C++: Fonctions
Passage des Arguments (suite)Passage des Arguments (suite)
Deux façons de passer les arguments par référence (suite)utilisation des références
void increment(int& value){
value += 1;}void main(){
int counter=100;cout << "Before increment, counter is = "
<< counter << endl;increment(counter);cout << "After increment, counter is = "
<< counter << endl;}
produitBefore increment, counter is = 100After increment, counter is = 101
© 1997-2003 Fabio HERNANDEZ125POO en C++: Fonctions
Tableau comme ArgumentTableau comme Argument
Les tableaux en C++ ne sont jamais passés par valeurUn tableau est passé comme un pointeur à son premier élément (celui de la position zéro)Conséquences:
tout changement fait à un tableau à l'intérieur d'une fonction est effectué au tableau lui même et pas à une copiela taille du tableau (le nombre de positions) ne fait pas partie du type: la fonction ne connaît donc pas cette taille
© 1997-2003 Fabio HERNANDEZ126POO en C++: Fonctions
Tableau comme Argument (suite)Tableau comme Argument (suite)
Exemplevoid printArray(int* array, int howmany){
cout << "[";for (int pos=0; pos < howmany; pos++)
cout << " " << array[pos];cout << " ]" << endl;
}
void incrementArray(int* array, int howmany){
for (int pos=0; pos < howmany; pos++)array[pos] += 100;
}
La taille du tableau est aussi un paramètre
© 1997-2003 Fabio HERNANDEZ127POO en C++: Fonctions
Tableau comme Argument (suite)Tableau comme Argument (suite)
Exemple (suite)void main(){
const int MaxItems = 5;int itemTable[MaxItems]={5, 10, 15, 20, 25};
cout << "Originally, itemTable is: ";printArray(itemTable, MaxItems);
incrementArray(itemTable, MaxItems);
cout << "After increment, itemTable is: ";printArray(itemTable, MaxItems);
}
produitOriginally, itemTable is: [ 5 10 15 20 25 ]After increment, itemTable is: [ 105 110 115 120 125 ]
© 1997-2003 Fabio HERNANDEZ128POO en C++: Fonctions
Tableau comme Argument (suite)Tableau comme Argument (suite)
Exemple (suite)La fonction printArray ne modifie pas le tableau passé en argumentOn devrait donc la définir de la façon suivante
void printArray(const int* array, int howmany){
cout << "[";for (int pos=0; pos < howmany; pos++)
cout << " " << array[pos];cout << " ]" << endl;
}
© 1997-2003 Fabio HERNANDEZ129POO en C++: Fonctions
FonctionsFonctions InlineInline
Parfois le temps d'exécution d'une fonction est petit comparé au temps nécessaire pour appeler la fonctionLe mot clé inline informe le compilateur qu'un appel à cette fonction peut être remplacé par le corps de la fonctionExemple
inline int max(int a, int b){
return (a < b) ? b : a;}
void main(){
int m = max(134, 876);}
© 1997-2003 Fabio HERNANDEZ130POO en C++: Fonctions
FonctionsFonctions InlineInline (suite)(suite)
Le compilateur génère le code équivalent à l'expansion de la fonction, comme si l'on avait écrit
void main(){
int m = (134 < 876) ? 876 : 134;}
Conséquences:programme plus rapideprogramme plus gros
Les fonctions inline doivent être définies dans des fichiers d'entête (.h) qui seront inclus dans des fichiers source (.cpp), pour que le compilateur puisse faire l'expansion
© 1997-2003 Fabio HERNANDEZ131POO en C++: Fonctions
Portée des VariablesPortée des Variables
Une définition de variable introduit un identificateurIl ne peut être utilisé que dans une partie du source du programme (portée)Une variable définie à l'intérieur d'une fonction (variable locale) peut être utilisée à partir de sa définition jusqu'à la fin du bloc où la définition apparaît
void swap(int& a, int& b){
int temp = a; // temp is a local variablea = b;b = temp;
}
© 1997-2003 Fabio HERNANDEZ132POO en C++: Fonctions
Portée des Variables (suite)Portée des Variables (suite)
Une variable définie en dehors d'une fonction ou d'une classe, (variable globale), est visible à partir de sa définition jusqu'à la fin du fichier source (.cpp) où sa définition apparaîtUne variable peut être définie dans un bloc avec le même nom qu'un identificateur déjà existant: dans ce cas, cette variable cache la variable du bloc externe ou la variable globale qui porte le même nom
© 1997-2003 Fabio HERNANDEZ133POO en C++: Fonctions
Portée des Variables (suite)Portée des Variables (suite)
Exempleint count; // global variable
void dummy(){
int count; // local count, hides globalcount = 100; // modifies local countwhile (count > 0) {
// do something--count;
}}
void increment(){
count += 1; // modifies global count}
© 1997-2003 Fabio HERNANDEZ134POO en C++: Fonctions
Durée de Vie des VariablesDurée de Vie des Variables
Lors de l'exécution du programme, chaque objet est créé quand sa définition apparaît et est détruit quand son identificateur sort de contexteEn particulier, les variables locales sont créées (allocation demémoire dans la pile d'exécution) au moment de l'invocation (activation) de la fonctionElles disparaissent quand la fonction finit son exécutionLes variables(objets) globales sont créées et initialisées une seule fois et existent jusqu'à la fin de l'exécution du programme
© 1997-2003 Fabio HERNANDEZ135POO en C++: Fonctions
Durée de Vie des Variables (suite)Durée de Vie des Variables (suite)
A l'aide du mot clé static le programmeur peut définir une variable locale de façon à ce qu'elle existe jusqu'à la fin du programmeCe type des variables sont initialisées une seule foisExemple
void dummy(){
static int count=1; // created and initialized// only once
int local=100; // created and initialized// at each call
cout << " local = " << local <<<< " count = " << count << endl;
++count;}
© 1997-2003 Fabio HERNANDEZ136POO en C++: Fonctions
Durée de Vie des Variables (suite)Durée de Vie des Variables (suite)
Exemple (suite)
void main(){
for (int i=0; i < 5; i++)dummy();
}
produitlocal = 100 count = 1local = 100 count = 2local = 100 count = 3local = 100 count = 4local = 100 count = 5