Polycopie-Pooc - 2019
Polycopie-Pooc - 2019
Polycopie-Pooc - 2019
Département Électronique
Boubekeur BOUKHEZZAR
Laboratoire d’Automatique
et de Robotique de Constantine (LARC)
Département électronique, Université Constantine 1,
Campus Ahmed Hamani, Route de Aı̈n-El-Bey,
25017 Constantine, Algérie
[email protected]
Avant-propos
i
(ouvrages) qu’en version électronique sur la toile. Des ouvrages de références dépassant
souvent les 1000 pages sont assez exhaustifs sur ce sujet et sont conseillés aux étudiants
en guise de complément, particulièrement lors de la préparation de leurs mini-projets.
Le document est divisé en trois parties :
1. La première contient les notes de cours mises à la disposition des étudiants et utilisées
lors du cours présentiel.
2. La seconde contient la majorité TP présentés aux étudiants.
3. La dernière partie regroupe les mini-projets proposés aux étudiants durant les années
passées.
La bibliographie utilisée est présentée à la fin du document.
Boubekeur Boukhezzar
ii
Table des matières
I Notes de cours xi
1 Éléments de Base 1
1.1 Aperçu général . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.1 Bref historique du langage C++ . . . . . . . . . . . . . . . . . . . . 1
1.1.2 Liens du C++ avec les autres langages . . . . . . . . . . . . . . . . 1
1.2 Structure d’un programme en C++ . . . . . . . . . . . . . . . . . . . . . 2
1.3 Création d’un programme en C++ . . . . . . . . . . . . . . . . . . . . . . 2
1.3.1 Édition du programme . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3.2 Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3.2.1 Traitement par le préprocesseur . . . . . . . . . . . . . . . 3
1.3.2.2 Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3.3 Edition de liens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.4 Les fichiers d’entête . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.5 Le préprocesseur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.6 Les commentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.6.1 Les commentaires libres (par bloc) . . . . . . . . . . . . . . . . . . 5
1.6.2 Les commentaires de ligne (de fin de ligne) . . . . . . . . . . . . . 5
1.7 Les variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.7.1 Déclaration des variables . . . . . . . . . . . . . . . . . . . . . . . 5
1.7.2 Type des variables . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.7.2.1 Les types entiers . . . . . . . . . . . . . . . . . . . . . . . 6
1.7.2.2 Les types réels ou flottants . . . . . . . . . . . . . . . . . 6
1.7.2.3 Les types caractère . . . . . . . . . . . . . . . . . . . . . . 6
1.7.2.4 Le type booléen . . . . . . . . . . . . . . . . . . . . . . . . 6
1.7.3 Règles d’écriture des identificateurs . . . . . . . . . . . . . . . . . . 7
1.8 Les constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.8.1 Définition d’une constante à l’aide du préprocesseur . . . . . . . . . 7
1.8.2 Les constantes énumérées . . . . . . . . . . . . . . . . . . . . . . . 8
1.9 Les opérateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.9.1 Opérateurs d’affectation . . . . . . . . . . . . . . . . . . . . . . . 8
1.9.1.1 L’opérateur d’affectation . . . . . . . . . . . . . . . . . . . 8
1.9.1.2 Autres opérateurs . . . . . . . . . . . . . . . . . . . . . . . 9
1.9.2 Les opérateurs arithmétiques . . . . . . . . . . . . . . . . . . . . . 9
1.9.3 Les opérateurs logiques . . . . . . . . . . . . . . . . . . . . . . . . 9
1.9.4 Les opérateurs de comparaison . . . . . . . . . . . . . . . . . . . . 9
iii
1.9.5 Les Opérateurs d’incrémentation et de décrémentation . . . . . . . 10
1.9.6 Opérateurs binaires . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.9.7 Opérateurs ternaire . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.9.8 Opérateurs sizeof . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.10 Les entrées-sorties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.10.1 Les entrées : cin . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.10.2 Les sorties : cout . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.10.2.1 Afficher un message . . . . . . . . . . . . . . . . . . . . . 12
1.10.2.2 Affichage d’une variable avec message . . . . . . . . . . . 12
2 Structures de Contrôle 13
2.1 L’instruction if-else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.2 La boucle while (tant que) . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.3 La boucle do-while (faire-tant que) . . . . . . . . . . . . . . . . . . . . . 15
2.4 La boucle for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.5 L’instruction switch-case . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.6 L’instruction break . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.7 L’instruction continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.8 L’instruction exit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
iv
3.4.2 Manipulation d’une structure . . . . . . . . . . . . . . . . . . . . . 28
3.4.3 Utilisation globale d’une structure . . . . . . . . . . . . . . . . . . . 28
3.4.4 Initialisation d’une structure . . . . . . . . . . . . . . . . . . . . . . 28
4 Les fonctions 29
4.1 Généralités . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.1.1 Définition et avantages des fonctions . . . . . . . . . . . . . . . . . 29
4.1.2 Caractéristiques des fonctions . . . . . . . . . . . . . . . . . . . . . 29
4.2 Déclaration d’une fonction, prototype . . . . . . . . . . . . . . . . . . . . 30
4.2.1 Prototype d’une fonction . . . . . . . . . . . . . . . . . . . . . . . . 30
4.2.1.1 Syntaxe de déclaration . . . . . . . . . . . . . . . . . . . . 30
4.3 Appel d’une fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.4 Définition d’une fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.4.1 Syntaxe de définition . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.4.2 Argument muets (fictifs) et arguments effectifs . . . . . . . . . . . . 32
4.4.3 Variables locales . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.4.4 Variables globales . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.5 Passage d’arguments aux fonctions . . . . . . . . . . . . . . . . . . . . . . 33
4.5.1 Le passage par valeur . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.5.2 Le passage par pointeur . . . . . . . . . . . . . . . . . . . . . . . . 35
4.5.3 Le passage par référence . . . . . . . . . . . . . . . . . . . . . . . . 36
4.6 Passage et retour d’un tableau à une fonction . . . . . . . . . . . . . . . . 37
4.6.1 Passage d’un tableau à une fonction . . . . . . . . . . . . . . . . . . 37
4.6.1.1 Syntaxe de déclaration : . . . . . . . . . . . . . . . . . . . 37
4.6.1.2 Syntaxe d’appel . . . . . . . . . . . . . . . . . . . . . . . . 37
4.6.2 Retour d’un tableau par une fonction . . . . . . . . . . . . . . . . . 38
4.6.2.1 Syntaxe de déclaration : . . . . . . . . . . . . . . . . . . . 38
4.6.2.2 Syntaxe d’appel . . . . . . . . . . . . . . . . . . . . . . . . 38
4.7 Passage d’une structure à une fonction . . . . . . . . . . . . . . . . . . . . 38
4.8 Pointeur vers une fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
v
5.5.3 L’objet courant et le mot-clé this . . . . . . . . . . . . . . . . . . . 46
5.5.4 Affectation des objets . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5.6 Constructeurs et destructeurs . . . . . . . . . . . . . . . . . . . . . . . . . 47
5.6.1 Constructeurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5.6.2 Destructeurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
7 Héritage 55
7.1 Déclaration d’une classe dérivée . . . . . . . . . . . . . . . . . . . . . . . . 55
7.1.1 Classe dérivée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
7.1.2 Syntaxe de déclaration d’une classe dérivée . . . . . . . . . . . . . . 55
7.2 Héritage et protection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.3 Spécification de l’héritage . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
7.4 Appel des constructeurs et destructeurs . . . . . . . . . . . . . . . . . . . . 59
7.4.1 Dérivation d’une classe possédant un constructeur avec arguments . 60
7.4.2 Quelques règles sur les constructeurs . . . . . . . . . . . . . . . . . 61
vi
8.3.3.2 Ouverture et fermeture implicite d’un fichier . . . . . . . . 69
8.3.4 Lecture et écriture sur un fichier . . . . . . . . . . . . . . . . . . . . 70
II Travaux pratiques 83
1 Éléments de Base 87
1.1 Objectifs du TP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
1.2 Partie 1 : Entrées et sorties avec les flots cin et cout . . . . . . . . . . . . 87
1.3 Partie 2 : Manipulation des opérateurs . . . . . . . . . . . . . . . . . . . . 87
2 Structures de Contrôle 89
2.1 Objectifs du TP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
2.2 Partie 1 : boucles while, do-while . . . . . . . . . . . . . . . . . . . . . . 89
2.3 Partie 2 : Calcul du factoriel . . . . . . . . . . . . . . . . . . . . . . . . . . 89
2.4 Partie 3 : Algorithme d’Euclide . . . . . . . . . . . . . . . . . . . . . . . . 89
3 Les Tableaux 91
3.1 Objectifs du TP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
3.2 Partie 1 : Affichage inverse d’un tableau . . . . . . . . . . . . . . . . . . . 91
3.3 Partie 2 : Lecture et affichage d’un tableau-Somme de deux tableaux . . . 91
5 Les fonctions 95
vii
5.1 Objectifs du TP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
5.2 Partie 1 : Déclaration d’une structure . . . . . . . . . . . . . . . . . . . . . 95
5.3 Partie 2 : Manipulation par pointeur . . . . . . . . . . . . . . . . . . . . . 95
5.4 Partie 3 : Utilisation des fonctions . . . . . . . . . . . . . . . . . . . . . . . 95
8 Héritage 101
8.1 Partie 1 : Classe modélisant un mammifère . . . . . . . . . . . . . . . . . . 101
8.2 Partie 2 : Classes dérivées modélisant un homme et un chien . . . . . . . . 101
9 Polymorphisme 103
9.1 Partie 1 : Classe modélisant un compte bancaire . . . . . . . . . . . . . . . 103
9.2 Partie 2 : Classe modélisant un compte bancaire avec découvert . . . . . . 104
9.3 Partie 3 : Sauvegarde des comptes dans un fichier . . . . . . . . . . . . . . 104
2 2011-2012 111
2.1 Présentation du Mini-Projet . . . . . . . . . . . . . . . . . . . . . . . . . . 111
2.2 Fonctions de l’application . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
2.2.1 Gestion de la liste des livres disponibles . . . . . . . . . . . . . . . . 111
2.2.2 Gestion de la liste des clients . . . . . . . . . . . . . . . . . . . . . 111
2.2.3 Gestion de la liste des commandes . . . . . . . . . . . . . . . . . . . 112
2.3 Caractérisations des objets de l’application . . . . . . . . . . . . . . . . . . 112
2.4 Travail demandé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
2.4.1 Important ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
2.4.2 Travail à remettre . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
3 2012-2013 115
3.1 Présentation du Mini-Projet . . . . . . . . . . . . . . . . . . . . . . . . . . 115
3.2 Fonctionnalités de l’application . . . . . . . . . . . . . . . . . . . . . . . . 115
3.2.1 Gestion des championnat . . . . . . . . . . . . . . . . . . . . . . . . 115
3.2.2 Gestion des équipes . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
3.2.3 Gestion du calendrier . . . . . . . . . . . . . . . . . . . . . . . . . . 116
viii
3.2.4 Gestion des résultats . . . . . . . . . . . . . . . . . . . . . . . . . . 116
3.2.5 Gestion du classement . . . . . . . . . . . . . . . . . . . . . . . . . 116
3.3 Travail demandé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
3.3.1 Important ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
3.3.2 Travail à remettre . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
4 2015-2016 119
4.1 Présentation du Mini-Projet . . . . . . . . . . . . . . . . . . . . . . . . . . 119
4.2 Fonctionnalités de l’application . . . . . . . . . . . . . . . . . . . . . . . . 119
4.2.1 Gestion des chaı̂nes . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
4.2.2 Gestion des satellites . . . . . . . . . . . . . . . . . . . . . . . . . . 119
4.2.3 Gestion du transpondeurs . . . . . . . . . . . . . . . . . . . . . . . 119
4.2.4 Menus utilisés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
4.2.5 Stockage des informations . . . . . . . . . . . . . . . . . . . . . . . 120
4.3 Travail demandé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
4.3.1 Important ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
4.3.2 Travail à remettre . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
ix
x
Première partie
Notes de cours
xi
Chapitre 1
Éléments de Base
1
Simula 67 Ada
?
BCPL -C - C++
6 I
@
@
Algol 68 Clu
Figure 1.1 – Dépendances du langage C++ de ses prédécesseurs
D’autres concepts tels que l’héritage multiple, les fonctions virtuelles pures et les na-
mespaces sont propres au langage C++.
2
1. Édition du programme.
2. Compilation.
3. Edition des liens.
1.3.2 Compilation
Le programme source est écrit dans un langage évolué. La compilation consiste à
traduire le programme source en langage machine. La compilation est effectué par un
programme appelé compilateur. La compilation est précédée par le traitement par le
préprocesseur.
1.3.2.2 Compilation
Elle produit un programme en langage machine. Ce résultat est appelé module objet et
porte généralement l’extension .obj. Le module objet n’est pas directement exécutable.
3
1 # include < iostream
Ces fichiers comportent les déclarations relatives aux fonctions prédéfinies. Le préprocesseur
copie le contenu de ce fichier dans le programme qu’il produit à l’endroit de la directive.
Le code compilé de ces fonctions est contenu dans les modules objet et il est rangé dans
des bibliothèques. Le fichier d’entête peut être nommé de trois façons :
Par son chemin absolu : Le préprocesseur recherche le fichier à cet emplacement même,
comme le montre la ligne de code ci-dessous :
1 # include " D :\ Program Files \ CodeBlocks \ include \ entete "
Listing 1.3 – Inclusion d’un fichier d’entête par son adresse absolue
Listing 1.4 – Inclusion d’un fichier d’entête contenu dans le répertoire courant
1.5 Le préprocesseur
Les fonctions du préprocesseur peuvent être résumées dans les points suivants :
1. Traiter le fichier source avant le compilateur.
2. Retirer les commentaires (compris entre /* et */ ou après //).
3. Prend en compte les lignes commençant par #.
4
1.6.1 Les commentaires libres (par bloc)
Ils commencent par /* et se termine par */. Ils peuvent s’étendre sur plusieurs lignes.
Un exemple est donné ci-dessous
1 /* + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
2 | Mon premier programme en C ++ |
3 + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ */
5
1.7.2.1 Les types entiers
Selon la taille en mémoire des variables, on distingue trois types entiers :
– short int (short)
– int
– long int (long)
Chaque type permet de représenter les données sur un certain nombre d’octets. Le nombre
d’octet définit la plage des valeurs prise par les variables de chaque type.
Lorsque la plage des valeurs est strictement positive, on utilise des variables non signés
(unsigned). On a lors les autres types suivants.
– unsigned short int
– unsigned long int
– unsigned int
6
9 float y = 54 e -01;
10 double z = 5.4;
11 unsigned char c = ’A ’ ;
12 return 0;
13 }
Un exemple
1 # define PI 3.14159
7
1.8.2 Les constantes énumérées
Le mot clé enum permet de définir des types puis de définir des variables de ce type
comme dans l’exemple suivant
Les variables c1 et c2 peuvent avoir cinq valeurs possibles : vert, rouge, bleu, noir et
blanc. Chaque constante énumérée possède une valeur numérique par défaut. Si aucune
valeur n’est spécifiée, la première constante va avoir la valeur 0, la seconde 1, etc . . . . Si
des valeurs sont spécifiées comme dans l’exemple suivant
Les valeurs prises par ces constantes énumérés vert, rouge, bleu, noir et blanc sont
respectivement 2, 3, 6, 7, 50.
8
1.9.1.2 Autres opérateurs
Opération Résultat
x+=y; x=x+y ;
x*=y ; x=x*y ;
x/=y ; x=x/y ;
x%=y ; x=x%y ;
Table 1.1 – Autres opérateurs
Opérateur Rôle
+ Addition
- Soustraction
* Multiplication
/ Division
% Modulo (Reste de division entière)
Table 1.2 – Opérateurs arithmétiques
Opérateur Rôle
&& Et
|| Ou
! Non (Not)
Table 1.3 – Opérateurs logiques
Opérateur Rôle
== Égal
!= Différent
< Strictement inférieur
<= Inférieur ou égal
> Strictement supérieur
>= Supérieur ou égal
Table 1.4 – Les Opérateurs de comparaison
9
1.9.5 Les Opérateurs d’incrémentation et de décrémentation
1 int x =1 ;
2 int y =0 ; y = x ++ ; // dans ce cas y =1 et x =2
3 x =1 ; // On r é i n i t i a l i s e x
4 y =++ x ; // dans ce cas x =2 et y =2
Opérateur Rôle
& Et binaire bit à bit
— Ou binaire bit à bit
∧ Ou exclusif bit à bit
∼ Complément à 1
<< Décalage de n bits à gauche
>> Décalage de n bits à droite
Table 1.6 – Opérateurs binaires
1 if (a > b ) z = a ;
2 else
3 z=b;
10
est équivalent à
1 z =( a > b ) ? a : b ;
1 int i =1 ;
2 cout << sizeof ( i ) < < " \ n " ; // affiche 4
3 cout << sizeof ( int ) < < " \ n " ; // affiche 4
1 cin > > variable1 > > variable2 > >... > > varaibleN ;
variable1, variable2,..., variableN sont les noms des variables qui vont contenir les
données saisies à partir du clavier. L’exemple suivant illustre son utilisation
1 int i , j ;
2 float z ;
3 char s , nom [12] ;
4 cin > > i > > j > > z > > s > > nom ;
11
1.10.2.1 Afficher un message
Le message est placé entre deux guillemets après un cout
1 int i =1 ;
2 int j =2 ;
3 cout < < i < < " + " <<j < < " = " << z ;
affichera 1+2=3.
Le changement de ligne se fait par \n et la tabulation par \t.
Plus de détails sur le concept et l’utilisation des flots seront donnés au chapitre 8
12
Chapitre 2
Structures de Contrôle
1 if ( condition ) {
2 // Bloc d ’ i n s t r u c t i o n s 1
3 } else {
4 // Bloc d ’ i n s t r u c t i o n s 2
5 }
L’expression condition est évaluée. Si elle est vraie (non nulle), le bloc d’instructions 1
est exécuté. Si elle est fausse (nulle), le bloc d’instructions 2 est exécuté. Un exemple est
donné dans le listing 2.2
Exemple 2.1 (Instruction if-else)
1 # include < iostream >
2
3 using namespace std ;
4
5 int main () {
6 int a ;
7 cout < < " Entrez un entier : " ;
8 cin > > a ;
9 if ( a >=0)
10 {
11 cout < < " \ n " <<a < < " est positif " ;
12 }
13 else
14 {
15 cout < < " \ n " <<a < < " est négatif " ;
16 }
17 return 0;
18 }
13
Remarque 2.1
Si le bloc d’instructions 1 ou 2 est composé d’une seule instruction, les accolades ne sont
pas nécessaires, mais il est conseillé de les mettre.
Remarque 2.2
L’instruction if peut être utilisée toute seule sans le else. Dans ce cas, l’instruction (ou
le bloc d’instructions) est exécuté si la condition est vraie. Sinon, le programme passe à
l’instruction suivante.
S’il existe plus de deux alternatives, elles s’expriment avec des else if (condition).
Le listing 2.3 illustre ceci
Exemple 2.2 (Instruction if-else if)
1 # include < iostream .h > # include < iostream >
2
3 using namespace std ;
4
5 int main () {
6 int a ;
7 cout < < " Entrez un entier : " ;
8 cin > > a ;
9 if ( a >0)
10 {
11 cout < < " \ n " <<a < < " est positif " ;
12 }
13 else if ( a ==0)
14 {
15 cout < < " \ n " <<a < < " est nul " ;
16 }
17 else
18 {
19 cout < < " \ n " <<a < < " est négatif " ;
20 }
21 return 0;
22 }
1 while ( condition ) {
2 // Bloc d ’ i n s t r u c t i o n s
3 }
Le bloc d’instruction est répété tant que condition est vérifiée (non nulle). Pour la boucle
while, la condition est vérifiée avant l’entrée dans le bloc. La boucle peut ne jamais être
exécutée si la condition n’est initialement pas vérifiée. Le programme 2.5 met en œuvre
l’utilisation de l’instruction while
Exemple 2.3 (Instruction while)
14
1 // Affiche les lettres de l ’ alphabet en majuscule s
2 # include < iostream >
3
4 using namespace std ;
5
6 int main () {
7 char i = ’A ’;
8 while ( i <= ’Z ’)
9 {
10 cout < < i < < " \ n " ;
11 i ++;
12 }
13 }
1 do
2 {
3 // Bloc d ’ i n s t r u c t i o n s
4 } while ( condition ) ;
Le test de la condition se fait à la fin de la boucle. Si la condition est vraie, la boucle est
réexecutée. Contrairement à la boucle while, le bloc d’instruction est exécuté au moins
une fois. Le listing 2.7 donne un exemple de l’utilisation de cette instruction.
Exemple 2.4 (Instruction do-while)
1 # include < iostream >
2 // Affiche les 10 chiffres
3 using namespace std ;
4
5 int main ()
6 {
7 int i =0;
8 do
9 {
10 cout < < i < < " \ n " ;
11 i ++;
12 }
13 while (i <=9);
14 return 0;
15 }
15
1 for ( expression 1 ; expressio n 2 ; expression 3 )
2 {
3 // Bloc d ’ i n s t r u c t i o n s
4 }
1 switch ( expression )
2 {
3 case val1 : // i n s t r u c t i o n 1 ou bloc d ’ i n s t r u c t i o n s 1
4 break ;
5 case val2 : // i n s t r u c t i o n 2 ou bloc d ’ i n s t r u c t i o n s 2
6 break ;
7 ...
16
8 default : // instructi o n ou bloc d ’ i n s t r u c t i o n s par défaut
9 }
L’expression est évaluée à l’entrée de la boucle switch. Elle doit donner un résultat de
type entier. val1, val2 sont des constantes de type entier. L’exécution de l’instruction se
fait à partir du case dont la valeur correspond à celle de l’expression évaluée. L’exécution
peut continuer pour les autres case jusqu’à rencontrer un break. Si la valeur de l’ex-
pression ne correspond à aucune des valeurs des case, c’est les instructions de default
qui sont exécutée. Un exemple d’utilisation de l’instruction switch-case est donné par
le programme 2.11
Exemple 2.6 (Instruction switch-case)
1 # include < iostream >
2
3 using namespace std ;
4 int main ()
5
6 {
7 int i ;
8 cout < < " Entrez 1 à 4 pour afficher une lettre de l ’ alphabet " ;
9 cin > > i ;
10 switch ( i )
11 {
12 case 1 :
13 cout < < " A " ;
14 break ;
15 case 2 :
16 cout < < " B " ;
17 break ;
18 case 3 :
19 cout < < " C " ;
20 break ;
21 case 4 :
22 cout < < " D " ;
23 break ;
24 default :
25 cout < < " Erreur " ;
26 }
27 return 0;
28 }
17
2.8 L’instruction exit
Elle termine l’exécution d’un programme. Elle permet de retourner une valeur n au
système d’exploitation par exit(n).
18
Chapitre 3
Remarque 3.1
La taille d’un tableau doit être une constante entière. Elle doit être connue au moment de
la compilation. Une déclaration de la forme int tab [n], où n est une variable entière
génère une erreur à la compilation, car le compilateur ne connaı̂t pas la taille de l’espace
nécessaire qu’il doit réserver pour stocker les éléments du tableau.
19
Il est commun d’utiliser une directive pour déclarer une constante qui définira la taille
de tous les tableaux d’un programme comme montré ci-dessous
1 # define dim 10
2 int tab [ dim ]; // tableau de dix entiers
3 float x [ dim ]; // tableau de dix réels
Listing 3.3 – Utilisation d’une directive pour la déclaration de la dimension d’un tableau
1 int i =5;
2 tab [0]; // accès au premier élément du tableau
3 tab [ i ]; // accès au 6 ème élément du tableau
4 tab [2* i -1]; // accès au 10 ème élément du tableau
Remarque 3.2
Le compilateur ne signale pas d’erreur s’il y a un dépassement de bornes. Par exemple, si
tab est un tableau de dimension 10, écrie tab[15] n’est pas une erreur que le compilateur
détectera.
20
1 int tab [5]={1 ,2} ; // affecte à tab [0] et tab [1] les valeurs 1 et 2 ,
2 // les autres sont à 0.
Lorsque la taille du tableau n’est pas indiquée, et que le tableau est initialisé par énumération,
le compilateur peut déterminer la taille du tableau en comptant les valeurs.
Le principe de manipulation d’un tableau à plusieurs dimensions est le même que celui
de la manipulation d’un tableau à une dimension. 0n peut initialiser un tableau à deux
dimensions par énumération en plaçant les lignes entres des accolades. Dans l’exemple
suivant, L’élément tab[0][0] prend la valeur 1. L’élément tab[0][1] prend la valeur 2.
21
3.1.3.1 Déclaration d’une chaı̂ne de caractères
Cette déclaration peut se faire de deux façons
1 char ch [3] = { ’A ’ , ’B ’ , ’ C ’ };
Listing 3.10 – Déclaration d’une chaı̂ne de caractères par une liste de constantes caractères
1 type * nom
22
&p=0x20 - adresse de a :
&a=0x30
&a=0x30 - valeur de a :
a= 76
3.2.2.1 Opérateur *
Cet opérateur permet d’accéder au contenu de la variable pointée.
Comme le montre la figure 3.1, le pointeur p pointe l’entier a dont l’adresse est 0x30.
a : Désigne le contenu de a.
&a : Désigne l’adresse de a.
p : Désigne le contenu du pointeur, c’est-à-dire l’adresse de a
*p : Désigne le contenu pointé par le pointeur p, c’est à dire la variable a.
&p : Désigne l’adresse du pointeur p.
23
7 int a =1;
8 int * p =& a ;
9 cout < < " Adresse de a : " < <& a < < ’\ n ’;
10 cout < < " Adresse p : " <<p < < ’\ n ’;
11 cout < < " Adresse p +1: " << p +1 < < ’\ n ’;
12 return 0;
13 }
Ce programme affiche
1 Adresse de a :0 x23ff74
2 Adresse p :0 x23ff74
3 Adresse p +1 :0 x23ff78
Le pointeur p s’est décalé de 4 octets en lui rajoutant 1 qui est la taille de l’espace mémoire
occupé par une variable de type int.
1 int A [10];
2 int * p ;
3 p = A ; // est équivalen t e à p = & A [0];
Dans cet exemple, après l’instruction p = A, le pointeur p pointe sur A[0]. De façon
générale, soit p un pointeur : si p pointe sur une composante quelconque d’un tableau,
alors
– (p+1) pointe sur la composante suivante.
– (p + i) pointe sur la ième composante devant p.
– (p - i) pointe sur la ième composante derrière p.
– *(p) désigne le contenu de A[0].
– *(p + 1) désigne le contenu de A[1].
– *(p + 2) désigne le contenu de A[2].
– *(p + i) désigne le contenu de A[i].
Un tableau peut donc être déclaré de deux façons :
24
1 # include < iostream >
2
3 using namespace std ;
4
5 int main ()
6
7 {
8 int tab [10];
9 int * p ;
10 p = tab ; // équivaut à p = & tab [0];
11 * p =1; // équivaut à tab [0] = 1;
12 *( p +1) =2; // équivaut à tab [1]=2;
13 return 0;
14 }
1 int * p [5] ; // tableau de cinq pointeurs vers des int int (* p )[5];
2 // pointeur vers un tableau int de 5 éléments
25
1 type ** nom
avec deux opérateurs d’indirection * pour désigner que c’est un pointeur vers un pointeur
vers une donnée du type spécifié. L’exemple suivant déclare un double pointeur vers un
entier initialisé avec l’adresse d’un pointeur vers un entier lui même initialisé avec l’adresse
d’un entier.
1 int i =1 ;
2 int * p =& i ; // pointeur vers i
3 int ** pp =& p ; // pointeur vers pointeur vers i
L’exemple suivant montre l’allocation d’un espace mémoire pour 10 variables de type int.
1 int * p ;
2 p = new int [10] ; // alloue de la mémoire pour 10 variables int
3 // et initialise le pointeur p avec le début
4 // du bloc mémoire
On alloue de l’espace mémoire pour 10 entiers et on récupère l’adresse de cet espace dans
un pointeur de même type.
– Il est possible de faire l’allocation directement au moment de la déclaration du poin-
teur.
– Si l’allocation mémoire échoue faute d’espace, la valeur du pointeur sera égale à NULL
(NULL est une constante prédéfinie du C++ qui vaut zéro).
– Il est conseillé de vérifier que le pointeur n’est pas égal à NULL après l’utilisation de
new.
L’exemple suivant montre l’allocation mémoire au moment de la déclaration et le test si
l’allocation mémoire est réussie.
1 int * p = new int [10] ;
2 if ( p == NULL ) cout < < " L ’ allocation mémoire a échoué " ;
26
L’allocation dynamique de la mémoire permet de définir des tableaux dynamiques dont la
dimension est spécifiée au moment de l’exécution comme le montre l’exemple suivant
1 int n ;
2 cout < < " Nombre d ’ éléments " ;
3 cin > > n ;
4 int * p = new int [ n ] ;
Même si on appel l’opérateur delete sur un pointeur, celui-ci continue d’avoir la valeur
de l’adresse de ce espace mémoire. Après l’appel de delete sur un pointeur, il faut le
remettre à 0.
27
3.4.2 Manipulation d’une structure
L’accès à un champ d’une variable structure se fait en suivant d’un point (’.’) le nom de
la variable structure, suivi du nom du champ. Ce champ peut alors être manipulé comme
n’importe quelle variable du type correspondant.
1 art1 . numero = 15 ;
2 cin >> art2 . prix ;
3 art1 . numero ++ ;
1 art1 = art2 ;
au lieu de
Une structure peut être aussi initialisée avec les éléments d’une structure du même type
1 struct article
2 {
3 .....
4 } ;
5 main ()
6 {
7 article e1 = { ..... } ;
8 Article e2 = e1 ; // les valeurs des champs de e1 sont recopiés
9 // dans ceux de e2
10 ...
11 }
Listing 3.34 – Initialisation d’une structure avec les éléments d’une autre structure
28
Chapitre 4
Les fonctions
4.1 Généralités
L’utilisation des fonctions a pour but de décomposer un problème en sous-problèmes
moins complexes et les traiter séparément. L’autre avantage des foncions est la réutilisabilité
du code. Si une fonction est suffisamment générique, elle peut être utilisée dans un autre
contexte.
29
4.2 Déclaration d’une fonction, prototype
Il est nécessaire de faire la différence entre la déclaration et la définition d’une fonction.
Ces deux opérations peuvent être faites séparément ou en même temps.
1 < type fonction > < nom fonction > ( type 1 , type 2 ,...) ;
Premier exemple
La fonction fct1() admet trois paramètres : Deux entiers et un réel. Elle retourne en
résultat un entier. Elle est donc de type int.
Deuxième exemple
1 float fct2 () ;
La fonction fct2() ne reçoit aucun paramètre (parenthèses vides) et retourne un réel (de
type float). On aurait pu également écrire float fct2(void) ;
30
Troisième exemple
1 void fct3 ( int ) ;
Syntaxe d’appel
1 < nom fonction > ( paramètre1 , paamètre2 ,...) ;
Les paramètres de la fonction doivent avoir une valeur au moment de l’appel de la fonction.
Ces valeurs peuvent êtres des variables, des constantes ou des expressions.
31
4.4.2 Argument muets (fictifs) et arguments effectifs
Les arguments figurant dans l’en-tête de la définition de la fonction sont appelés argu-
ments muets, arguments formels ou paramètres formels. Ce sont des variables qui ont une
portée locale et qui sont initialisées avec les arguments fournis à la fonction lors de son
appel.
Les arguments fournis lors l’appel de la fonction se nomment des arguments effectifs
ou paramètres effectifs. Ces arguments peuvent êtres des variables, des constantes ou des
expressions. C’est cette expression qui sera alors transmise à la fonction.
Exemple 4.1 (Fonction somme)
1 # include < iostream >
2
3 using namespace std ;
4
5 int somme ( int , int ); // Déclarati o n de la fonction somme
6 int main ()
7 {
8 int a ,b , c ;
9 a =3;
10 b =4;
11 c = somme (a , b ); // appel de la fonction somme
12 cout < < a << " + " << b << " = " << c ;
13 return 0;
14 }
15 // Définitio n de la fonction somme
16 int somme ( int x , int y )
17 {
18 int z ; // variable locale
19 z=x+y;
20 return z ; // retourne la valeur de z
21 }
Dans cet exemple, on déclare d’abord une fonction somme avant le main qui reçoit deux
entiers et revoie leur somme. La définition de la fonction est faite après le main. Dans le
main, on appelle la fonction somme avec comme argument effectif les deux variables a et
b et on affecte son résultat à la variable entière z qui est une variable locale.
32
1 # include < iostream >
2
3 using namespace std ;
4
5 void fct (); // Déclarati o n de la fonction fct
6 int i ; // varaible globale
7 int main ()
8 {
9 i =5; // pas beson de declarer i , variable globale
10 int j =6; // variable locale
11 cout < < " \ n Avant appel de fct (): i = " <<i ;
12 cout < < " \ n Avant appel de fct (): j = " <<j ;
13 fct ();
14 cout < < " \ n Après appel de fct (): i = " <<i ;
15 cout < < " \ n Après appel de fct (): j = " <<j ;
16 return 0;
17 }
18
19 void fct ()
20 {
21 int j =3; // varaible locale
22 i = i +5;
23 j = j +5;
24 cout < < " \ n Dans fct (): i = " << i ;
25 cout < < " \ n Dans fct (): j = " << j ;
26 }
Le contenu de la variable locale j reprend sa valeur initiale dans main() après l’appel de
la fonction. Par contre, la variable globale i est modifiée et garde cette modification après
l’appel de la fonction.
33
4.5.1 Le passage par valeur
Le passage par valeur consiste à fournir à la fonction appelée une copie d’une variable
de la fonction appelante. Il s’agit de deux variables différentes, l’une étant simplement
initialisée avec la valeur de l’autre. L’exemple suivant est celui d’une fonction recevant ses
arguments par un passage par valeur
34
Exemple 4.3 (Passage d’arguments par valeur)
1 # include < iostream >
2
3 using namespace std ;
4
5 void P a s s a g e P a r V a l e u r ( int i ) // Déclarat io n et définitio n
6 {
7 i =10;
8 }
9 int main ()
10 {
11 int i =0;
12 P a s s a g e P a r V a l e u r ( i );
13 cout < < " Valeur de i : " <<i ;
14 return 0;
15 }
Listing 4.9 – Exemple d’une fonction recevant ses arguments par valeur
Le programme affiche
1 Valeur de i : 0
La variable i n’est pas modifiée par l’appel de la fonction PassageParValeur, car les
variables i dans PassageParValeur et main sont différentes même si elles portent le
même nom.
Listing 4.10 – Exemple d’une fonction recevant ses arguments par adresse
Le programme affiche
1 Valeur de i : 10
35
4.5.3 Le passage par référence
Les références permettent de désigner des variables déclarées dans une autre fonction.
Dans d’autres langages, les références sont nommées alias, c’est à dire un nom de variable
qui désigne une autre variable. Les références fournissent un concept proche de celui des
pointeurs et peuvent s’utiliser dans le même contexte.
La déclaration d’une référence se fait en plaçant l’opérateur & entre le type de la
référence et son nom. Les références doivent être initialisées au moment de leur déclaration.
Le passage par référence est illustré par cet exemple
Le passage d’argument par référence constitue une solution hybride entre le passage par
valeur et par pointeur. C’est la variable et non l’adresse qui est passée à la fonction
appelée, cependant, la référence permet de modifier la variable de la fonction appelante.
Listing 4.12 – Exemple d’une fonction recevant ses arguments par référence
Le programme affiche
1 Valeur de i : 10
36
4.6 Passage et retour d’un tableau à une fonction
Une fonction peut recevoir en argument et retourner des tableaux.
1 < type fonction > < nom fonction > ( < type tableau > [])
Il est également possible de passer l’adresse du premier élément du tableau à travers son
identificateur, en faisant un passage par pointeur. Ceci est montré sur l’exemple suivant
37
1 # include < iostream >
2
3 using namespace std ;
4
5 void affiche_nu m ( int *); // Déclarat io n
6
7 int main ()
8 {
9 int entiers []= {4 ,5 ,8 ,9};
10 affiche_n u m ( entiers );
11 return 0;
12 }
13 void affiche_nu m ( int * tab ) // Définitio n
14 {
15 int i ;
16 for ( i =0; i <4; i ++)
17 cout < < tab [ i ] < < " " ;
18 }
1 < type fonction > * < nom fonction > ( < types parametres > )
38
1 # include < iostream >
2
3 using namespace std ;
4
5 struct etudiant
6 {
7 char * nom ;
8 char * prenom ;
9 int age ;
10 };
11 void A f f i c h e E t u d i a n t V a l e u r ( etudiant ); // Déclarati o n
12 void A f f i c h e E t u d i a n t A d r e s s e ( etudiant *); // Déclarati o n
13 int main ()
14 {
15 etudiant personne1 = { " N O M _ E T U D I A N T " ," P R E N O M _ E T U D I A N T " ,22};
16 etudiant * p t r _ p e r s o n n e 1 =& personne1 ;
17 cout < < " PASSAGE PAR VALEUR \ n \ n " ;
18 A f f i c h e E t u d i a n t V a l e u r ( personne1 );
19 cout < < " PASSAGE PAR ADRESSE \ n \ n " ;
20 A f f i c h e E t u d i a n t A d r e s s e ( p t r _ p e r s o n n e 1 );
21 return 0;
22 }
23 void A f f i c h e E t u d i a n t V a l e u r ( etudiant etd ) // Définitio n
24 {
25 cout < < " Nom : " << etd . nom < < endl ;
26 cout < < " Prenomom : " << etd . prenom < < endl ;
27 cout < < " Age : " << etd . age < < " \ n \ n " ;
28 }
29 void A f f i c h e E t u d i a n t A d r e s s e ( etudiant * etd ) // Définition
30 {
31 cout < < " Nom : " << etd - > nom < < endl ;
32 cout < < " Prenomom : " << etd - > prenom < < endl ;
33 cout < < " Age : " << etd - > age < < " \ n \ n " ;
34 }
Syntaxe de déclaration :
1 < type retour > (* < nom poniteur >) ( < types parametres > )
Dans cette ligne de code, on déclare un pointeur vers une fonction retournant un réel et
ayant pour arguments deux entiers
39
L’exemple suivant illustre l’utilisation des pointeurs vers des fonctions
Exemple 4.10 (Pointeur vers une fonction)
1 # include < iostream >
2
3 using namespace std ;
4
5 int somme ( int , int );
6 int produit ( int , int );
7 int main ()
8 {
9 int a =2 , b =3;
10 int (* pfct )( int , int );
11 pfct = somme ;
12 cout < < " a + b = " << pfct (a , b ) < < endl ;
13 pfct = produit ;
14 cout < < " a * b = " << pfct (a , b ) < < endl ;
15 return 0;
16 }
17 int somme ( int x , int y )
18 {
19 return x + y ;
20 }
21 int produit ( int x , int y )
22 {
23 return x * y ;
24 }
Remarque 4.1
Les parenthèses permettent de distinguer entre un pointeur de fonction et une fonction
renvoyant un pointeur
40
Chapitre 5
5.1 Définitions
Les notions de classe et d’objet sont à la base de la programmation orientée objet. On
commencera par donner leurs définitions.
41
3 // déclarat io n des variables membres
4 type1 variable1 ;
5 type2 variable2 ;
6 ...
7 // déclarat io n des fonctions membres
8 type1 fonction1 ( type_arg1 , type_arg2 ,...) ;
9 type2 fonction2 ( type_arg1 , type_arg2 ,...) ;
10 ...
11 } ;
1 class ordinateur
2 {
3 char reference [15] ;
4 char marque [15];
5 int disque ;
6 int memoire ;
7 void afficher () ;
8 };
On a déclaré une classe ordinateur qui comporte quatre données membres et une fonction
membre afficher().
42
17 cin > > poid ;
18 }
19 void afficher ()
20 {
21 cout < < " \ n Race : " << race ;
22 cout < < " \ n Age : " << age ;
23 cout < < " \ n Poid : " << poid ;
24 }
25 };
26 int main ()
27 {
28 chien dog1 ;
29 dog1 . creer ();
30 dog1 . afficher ();
31 return 0;
32 }
On a défini une classe chien avec deux fonctions membres creer() et afficher() qui
sont définies directement à l’intérieur de la classe.
43
21 cin > > poid ;
22 }
23 void chien :: afficher ()
24 {
25 cout < < " \ n Race : " << race ;
26 cout < < " \ n Age : " << age ;
27 cout < < " \ n Poid : " << poid ;
28 }
29 int main ()
30 {
31 chien dog1 ;
32 dog1 . creer ();
33 dog1 . afficher ();
34 return 0;
35 }
44
15 }
16 int main ()
17 {
18 client personne1 ;
19 personne1 . code =10;
20 client personne2 ;
21 personne2 . initialis er (10);
22 return 0;
23 }
1 class A
2 {
3 private :
4 ...
5 public :
6 ...
7 private :
8 ...
9 } ;
Dans cet exemple, on définit une classe client avec des membres publics et des membres
privés.
Exemple 5.4 (Membres publics et privés d’une classe)
1 # include < iostream >
2
3 using namespace std ;
4
5 class client
6 {
7
8 public :
9 char nom [15];
10 int getCode ();
11 void setCode ( int );
12 private :
13 int code ;
14 };
45
15
16 int client :: getCode ()
17 {
18 return code ;
19 }
20 void client :: setCode ( int n )
21 {
22 code = n ;
23 }
24 int main ()
25 {
26 client personne1 ;
27 // personne1 . code =10; // non autorisée : code variable privée
28 client personne2 ;
29 personne2 . setCode (10);
30 cout < < " Code = " << personne2 . getCode ();
31 return 0;
32 }
5.5.2 Encapsulation
L’encapsulation est l’un des fondements de la POO. Elle permet d’utiliser un objet en
cachant son fonctionnement interne. Grâce à l’encapsulation, les données privées ne sont
pas accessibles de façon directe. Ceci permet de sécuriser les données qui ne peuvent pas
êtres altérées par un utilisateur extérieur.
Les utilisateurs de l’objet disposent d’une interface public pour utiliser l’objet. L’accès
aux données privées se fait alors uniquement par les fonctions membres de la classe. Un
autre avantage de l’encapsulation est de rendre l’implémentation de la classe transparente
aux utilisateurs. Tant que l’interface public de la classe n’a pas changée, les utilisateurs
peuvent continuer à utiliser la classe de la même façon même si l’implémentation de ses
données a changée. Grâce à l’encapsulation, on peut changer la façon dont les données
sont déclarées et stockées sans changer la façon dont elles sont utilisées.
46
5.5.4 Affectation des objets
Comme pour les structures, et contrairement aux tableaux, il est possible d’affecter un
objet à un autre objet à condition qu’ils soient de la même classe. Le listing 5.9 recopie
les données de l’objet personne1 vers personne2
1 ...
2 client personne1 , personne2 ;
3 personne1 . setCode (10);
4 cout < < " Code = " << personne1 . getCode ();
5 personne2 = personne1 ;
6 cout < < " Code = " << personne2 . getCode ();
7 ...
L’affectation recopie toutes les variables membres de l’objet à droite du = vers celle
l’objet à gauche. L’affectation globale entre objet est toujours possible même s’il existe des
membres privés. Par contre, l’affectation entre variables membres est possible seulement
si elles sont publics. L’écriture
5.6.2 Destructeurs
Comme le constructeur, le destructeur est une fonction membre spéciale qui possède
les propriétés suivantes :
1. Il porte le même nom que la classe et il est déclaré public.
47
2. Son nom est précédé du symbole tilde ~.
3. Son rôle est de libérer l’espace mémoire alloué aux objets qui ne sont plus utilisés.
4. C’est une fonction membre de la classe qui n’a pas de type de retour (même pas
void) et ne reçoit pas de paramètres.
5. Contrairement aux constructeurs, il n’existe qu’un seul destructeur.
6. Il est appelé automatiquement à la fin du programme.
Dans le listing 5.10, on définit une classe rectangle avec un constructeur et un destructeur
Le programme affiche
48
Chapitre 6
49
Le programme affiche
1 i =1
2 j =1
3 i =2
4 j =1
5 i =3
6 j =1
Les variables statiques locales sont initialisées au premier appel de la fonction. Par défaut,
elles sont initialisées à zéro.
1 class nom_classe {
2 static type < nom variable >
3 } ;
Sur le listing 6.3, la variable n est une variable statique commune aux objets a et b de la
classe maclasse. Par contre, chaque objet à une variable membre x différente qui lui est
personnelle.
Exemple 6.2 (Variables membres statiques)
1 # include < iostream >
2
3 using namespace std ;
4
5 class maclasse
6 {
7 static int n ;
8 double x ;
9 } ;
10 int main ()
11 {
12 maclasse a , b ;
13 return 0;
14 }
50
6.1.3 Initialisation des variables membres statiques
Les variables membres statiques sont initialisées en dehors de la déclaration de la classe.
Ceci permet d’éviter l’allocation d’emplacements différents si des modules objets, utilisant
cette classe, sont compilés séparément.
La variable membre statique est initialisée explicitement, à l’extérieur de la déclaration
de la classe.
1 class nom_classe
2 {
3 static type < nom variable >
4 } ;
5 type nom_classe :: < nom variable >= valeur initiale ;
Le programme affiche
1 Il y a 1 objets
2 Il y a 2 objets
3 Il reste 1 objets
4 Il reste 0 objets
51
6.2 Les fonctions membres statiques
Comme pour une donnée membre statique, une fonction membre statique est partagée
par toutes les instances d’une même classe. Au lieu d’être appelé avec un objet de la
classe, elle est appelée avec le nom de la classe.
Une fonction membre statique ne sait pas travailler sur un objet particulier de la classe.
Elle ne récupère pas le pointeur système this (voir section 5.5.3). Par conséquent, elle ne
peut pas accéder aux données membres d’un objet et elle ne peut pas appeler une fonction
membre non statique.
Les fonctions membres statiques sont généralement utilisées pour manipuler les données
statiques. Elles mettent en œuvre un traitement qui n’est pas lié aux objets de la classe
1 class nom_classe {
2 static type < nom variable >
3 public :
4 static type fonction (){ return variable ;}
5 } ;
6 type nom_classe :: < nom variable >= valeur initiale ;
Ci-dessous un exemple d’une fonction membre statique qui affiche le nombre d’instances
Exemple 6.4 (Fonctions membres statiques)
1 # include < iostream >
2
3 using namespace std ;
4
5 class objet
6 {
7 public :
8 int code ;
9 static int n b _ i n s t a n c e s ;
10 objet ( int x )
11 {
12 code = x ;
13 ++ n b _ i n s t a n c e s ;
14 cout < < " Il y a " << nb_instances < < " objets \ n " ;
15 }
16 ~ objet ()
17 {
18 -- n b _ i n s t a n c e s ;
19 cout < < " Il reste " << nb_instances < < " objets \ n " ;
20 }
21 static int affiche ()
22 {
23 return n b _ i n s t a n c e s ;
24 }
25 };
26 int objet :: n b _ i n s t a n c e s =0;
27 int main ()
28 {
29 objet obj1 = objet (1);
30
31 objet obj2 = objet (2);
32 cout < < " Nombre d ’ objets = " << objet :: affiche () < < ’\ n ’;
33 return 0;
34 }
52
6.3 Portée d’une fonction
Les fonctions membres d’une classe ont une portée limitée aux objets cette classe. Leur
appel est toujours précédé du nom de l’objet ou de la classe. Les fonctions définies à
l’extérieur des classes ont par contre une portée globale. Cette différence est illustrée par
l’exemple suivant
Exemple 6.5 (Portée des fonctions)
1 # include < iostream >
2
3 using namespace std ;
4
5 int foisdeux1 ( int a )
6 {
7 return 2* a ;
8 }
9 class maclasse
10 {
11 public :
12 int v ;
13 void foisdeux2 ()
14 {
15 v *= v ;
16 }
17 };
18 int main ()
19 {
20 int x =2 , y ;
21 y = foisdeux1 ( x ); // appel de la fonction foisdeux1 ()
22 maclasse obj ;
23 obj . v =2;
24 obj . foisdeux2 (); // appel de la fonction membre foisdeux2 ()
25 cout < <y < < ’\ n ’;
26 cout < < obj . v ;
27 return 0;
28 }
Le programme affiche
1 4
2 4
53
Une même fonction peut être amie de plusieurs classes. La technique de la fonction amie
permet le contrôle d’accès à la classe. Seules les fonctions déclarées amies à l’intérieur d’une
classe peuvent accéder à ces membres.
1 class A
2 {
3 private :
4 ...
5 public :
6 // Syntaxe pour une fonction amie globale
7 friend type fct ( arguments ) ;
8 // syntaxe pour une fonction amie membre d ’ une autre classe B
9 friend type B :: fct ( arguments ) ;
10 ...
11 };
1 class A
2 {
3 private :
4 ...
5 public :
6 friend class B ;
7 } ;
8 class B
9 {
10 };
L’amitié n’est pas commutative, si la classe B est amie de la classe A, ça ne veut pas dire
que A est amie de la classe B. De même, l’amitié entre classes n’est pas transitive. Si A est
amie de B et B amie de C, alors on ne peut pas conclure que A est amie de C.
54
Chapitre 7
Héritage
55
Avec la syntaxe du listing 7.1, la classe A est la classe de base (classe parent) et la classe
B est la classe dérivée (classe fille). La classe A doit obligatoirement être déclarée avant la
classe B.
Grâce à l’héritage, on peut définir une hiérarchie (arborescence) de classes. Il est possible
de dériver une nouvelle classe C à partir de la classe B qui elle même dérive de la classe A.
A chaque fois qu’un objet de la classe dérivée B est créé, C++ crée un objet de la classe
de base A. Un objet de la classe B peut être alors vu comme un objet de la classe A avec
des éléments supplémentaires, qui sont les membres spécifiques à la classe B qui ne sont
pas définis dans la classe A.
Les données membre de la classe de base sont allouées au moment de la déclaration
d’un objet de la classe dérivée, de la même façon que si un objet de la classe de base a
été déclaré. Ce processus de création automatique d’un objet de la classe de base si un
objet de la classe dérivée est déclaré se propage tout au long de la hiérarchie des classes.
Si B dérive de A et C dérive B, la déclaration d’un objet de la classe C crée des objets de
la classe B et A. L’exemple suivant montre une classe parent A dont dérive la classe B
Exemple 7.1 (Classe dérivée)
1 # include < iostream >
2
3 using namespace std ;
4
5 class A
6 {
7 public :
8 int i ;
9 void afficheI ();
10 };
11 class B : public A
12 {
13 public :
14 int j ;
15 void afficheIJ ();
16 };
17 void A :: afficheI ()
18 {
19 cout < < " i = " <<i < < " \ n " ;
20 }
21 void B :: afficheIJ ()
22 {
23 afficheI ();
24 cout < < " j = " <<j < < " \ n " ;
25 }
26 int main ()
27 {
28 B b;
29 b . i =1;
30 b . j =2;
31 b . afficheIJ ();
32 return 0;
33 }
Le programme affiche
1 i =1
2 j =2
56
On a déclaré une classe A dont tous les membres (données et fonctions membres) sont
déclarés sous l’étiquette public. La classe A possède une donnée membre i et une méthode
afficheI() qui permet d’afficher i. On déclare une classe B qui dérive de la classe A avec
un nouvel attribut j et une nouvelle méthode afficheIJ(). Dans ce cas, comme les
membres de la classe A sont déclarés public, ils sont accessibles par les membres de la
classe B. Ceci permet à la méthode afficheIJ() d’appeler la méthode afficheI(). Dans
le main(), un objet b de la classe B est créé. Ceci entraı̂ne la création d’un objet de la
classe A et l’objet b possèdera l’attribut i de la classe A. Comme cet attribut est public,
il a été affecté directement : b.i=1. L’application de la méthode afficheIJ() sur l’objet
b permet de faire appel à la méthode de la classe de base afficheI() et d’afficher ainsi
i et j.
57
18 public :
19 void init2 ( char *);
20 void affichage2 ();
21 };
22 void
23 mamifere :: init1 ( int a , int b )
24 {
25 age = a ;
26 poid = b ;
27 }
28 void mamifere :: affichage1 ()
29 {
30 cout < < " Age : " << age < < " \ n " ;
31 cout < < " Poid : " << poid < < " \ n " ;
32 }
33
34 void chien :: init2 ( char * c )
35 {
36 strcpy ( race , c );
37 }
38 void chien :: affichage2 ( )
39 {
40 affichage 1 ();
41 cout < < " Race : " << race < < " \ n " ;
42 }
43 int main ()
44 {
45 chien c ;
46 c . init1 (2 ,20);
47 c . init2 ( " bulldog " );
48 c . affichage2 ();
49 return 0;
50 }
Listing 7.3 – Exemple d’utilisation des étiquettes de protection dans les classes dérivées
Le programme affiche
1 Age : 2
2 Poid : 20
3 Race : bulldog
Les variables membres age, poid et la méthode affiche1() sont protégées. Elles peuvent
êtres utilisées par les méthodes de la classe mammifere ou celle de la classe chien mais ne
peuvent pas êtres accédées par un utilisateur de la classe.
Lors de l’appel d’une méthode par un objet de la classe dérivée, le compilateur vérifie
d’abord si c’est une méthode de la classe dérivée, s’il ne la trouve pas il regarde dans les
méthodes publics et protégées de la classe mère et ainsi de suite en remontant la hiérarchie
des classes.
58
si B dérive de A, cette spécification n’aura pas d’effet sur l’accessibilité des membres de A
dans B mais sur les classes dérivant de B. Cette spécification agit de la façon suivante :
public : Les étiquettes de protection des membres de la classe A restent inchangées dans
la classe B.
protected : Les membres public et protected de A deviennent protected dans B.
private : Les membres public et protected de A deviennent private dans B. Les
classes dérivées de B ne pourront plus accéder aux membres de A.
59
40 * m = new mamifere ();;
41 cout < < " Destructi on d ’ un objet de type mamifere \ n " ;
42 delete m ;
43 cout < < " Creation d ’ un objet de type chien \ n " ;
44 chien
45 * c = new chien ();
46 cout < < " Destructi on d ’ un objet de type chien \ n " ;
47 delete c ;
48 return 0;
49 }
Le programme affiche
60
27 : parc ( n )
28 {
29 }
30
31 int main ()
32 {
33 parcvoitu r e p (20);
34 cout < < " Nombre de places = " << p . get_nombre ();
35 return 0;
36 }
61
25 parcvoitu r e ( int n );
26 };
27 parc :: parc ( int n )
28 {
29 nombre = n ;
30 }
31 parcvoit u re :: parcvoitu r e ( int n )
32 : parc ( n )
33 {
34 }
35
36 int main ()
37 {
38 parcvoitu r e p ;
39 cout < < " Nobre de places = " << p . get_nombr e () < < " \ n " ;
40 parcvoitu r e m (20);
41 cout < < " Nobre de places = " << m . get_nombr e () < < " \ n " ;
42 return 0;
43 }
Le programme affiche
1 Nombre de places = 0
2 Nombre de places = 20
62
Chapitre 8
63
2. clog : C’est un flot de sortie, avec buffer intermédiaire, connecté à la sortie standard
d’erreur.
64
Exemple 8.1 ( Formatage avec de l’opérateur <<)
1 # include < iostream >
2
3 using namespace std ;
4
5 using namespace std ;
6 int main ()
7 {
8 int n = 10 ;
9 cout << " en décimal ( par defaut :) " << n << " \ n " ;
10 cout << " en hexadecim a l : " << hex << n << " \ n " ;
11 cout << " en decimal : " << dec < < n << " \ n " ;
12 cout << " en octal : " << oct << n << " \ n " ;
13 cout << " sans m a n i m u l a t e u r : " << n << " \ n " ;
14 bool b = 1 ;
15 cout << " par defaut : " << b << " \ n " ;
16 cout << " avec noboolalp h a : " << noboolalp ha << b << " \ n " ;
17 cout << " avec boolalpha : " << boolalpha << b << " \ n " ;
18 cout << " sans m a n i p u l a t e u r : " <<b < < " \ n " ;
19 return 0;
20 }
le programme affiche
La valeur du flot de sortie reste la même tant qu’on ne la modifie pas. Le manipulateur
boolalpha demande d’afficher les valeurs booléennes sous forme alphabétique (true et
false). Le manipulateur noboolapha demande d’afficher les valeurs booléennes sous forme
numérique 0 ou 1.
65
10 for ( i =0 ; i <12 ; i ++)
11 cout << setw (2) < < i << " : " << setw ( i ) << a << " \ n " ;
12 return 0;
13 }
le programme affiche
1 0 : ABC
2 1 : ABC
3 2 : ABC
4 3 : ABC
5 4 : ABC
6 5 : ABC
7 6 : ABC
8 7 : ABC
9 8 : ABC
10 9 : ABC
11 10 : ABC
12 11 : ABC
Si la valeur fournie à setw est plus courte que l’information à afficher, celle-ci ne sera pas
tronquée.
le programme affiche
1 par defaut : 123456
2 Nombre de chiffres s i g n i f i c a t i f s : 1 : 1 e +005
3 Nombre de chiffres s i g n i f i c a t i f s : 2 : 1.2 e +005
4 Nombre de chiffres s i g n i f i c a t i f s : 3 : 1.23 e +005
5 Nombre de chiffres s i g n i f i c a t i f s : 4 : 1.235 e +005
6 Nombre de chiffres s i g n i f i c a t i f s : 5 : 1.2346 e +005
7 Nombre de chiffres s i g n i f i c a t i f s : 6 : 123456
8 Nombre de chiffres s i g n i f i c a t i f s : 7 : 123456
66
8.2.2.4 Choix de la notation flottante et exponentielle
Le choix se fait avec les manipulateurs fixed pour la notation flottante et scientific
pour la notation exponentielle à un chiffre avant le point de mantisse. On peut en même
temps que le choix du type de la notation faire un choix de la précision. Dans ce cas, la
précision correspondra au nombre de chiffres après la virgule.
le programme affiche
67
8.3 Les fichiers
8.3.1 Connexion d’un flot de sortie à un fichier
Pour connecter un flot de sortie à un fichier, on crée un objet de la classe ofstream,
classe dérivant de ostream. La création se fait avec le constructeur de la classe ofstream.
On peut appeler le constructeur à deux arguments :
1. Le nom du fichier concerné (chaı̂ne de caractères).
2. Le mode d’accès, défini par une constante entière. Ce sont des constantes symbo-
liques prédéfinies de la classe ios.
Le fichier est crée et ouvert en écriture. La syntaxe de création d’un flot de sortie associé
à un fichier est la suivante
Le paramètre nom fichier est une chaı̂ne de caractères qui désigne le nom du fichier.
Le paramètre mode ouverture est optionnel. Il désigne le mode d’ouverture du fichier.
Il s’agit d’un entier qui peut prendre des valeurs qui sont contenues dans des constantes
symboliques dans le fichier d’entête ios.h.
Les différents modes d’ouverture qui sont regroupés dans le tableau 8.1
Mode Signification
ios ::in Ouverture en lecture (ifsream)
ios ::out Ouverture en écriture (ofstream)
ios ::app Ajout à la fin du fichier
ios ::ate Se place à la fin du fichier. Possibilité d’écrire partout
dans le fichier
ios ::trunc Le fichier existant est tronqué (contenu perdu)
ios ::nocreate Si le fichier n’existe pas, l’ouverture échoue
ios ::noreplace Si le fichier existe, l’ouverture échoue
Table 8.1 – Modes d’ouverture d’un fichier
68
8.3.3 Ouverture et fermeture d’un fichier
Un fichier doit être ouvert avant d’y effectuer une opération de lecture ou d’écriture.
Aussi, un fichier ouvert doit toujours être fermé s’il n’est plus utilisé. L’ouverture effectue
la liaison entre le programme et le fichier et la fermeture la termine.
En C++, le traitement des fichiers peut s’envisager de deux façons :
1. De façon conventionnelle en utilisant la bibliothèque standard du C (incluse dans
C++) sans faire appel aux flot.
2. En utilisant les flot grâce aux classes ifstream, ofstream et fstream.
En utilisant les flots, l’ouverture et la fermeture des fichiers peut se faire implicitement
ou explicitement. Dans le cas conventionnel (sans flot), elle doit se faire explicitement.
1 nom_flot . close () ;
Par contre, la fonction open possède deux paramètres : Un pointeur char qui référence
le nom du fichier et un nombre entier qui peut être fournit par les mêmes constantes
symboliques présentées au tableau 8.1. Ces constantes spécifient le mode d’ouverture
souhaité. La syntaxe de la fonction open est donnée par
Les classes ifstream, ofstream et fstream possèdent des constructeurs par défaut
(sans paramètres) . Ceci permet de créer des flots sans les associer à un fichier. Ces flots
pourront être utilisés par les fonctions open et close. Il est préférable d’ouvrir et de fermer
les fichiers de façon implicite. Toutefois, les opérations explicites peuvent êtres utiles dans
les cas suivants :
1. Lorsqu’un même fichier doit être ouvert en lecture et en écriture.
2. Lorsque le même flot doit être associé à plusieurs fichiers différents.
69
8.3.4 Lecture et écriture sur un fichier
La lecture et l’écriture sur des fichiers peut se faire de la même façon que les opérations
d’entrée-sortie sur clavier-écran. Au lieu des flots prédéfinis cin et cout, on utilise des
flots qui sont des instances des classes ifstream, ofstream et fstream.
Les entrées-sorties formatées se font de la même façon que celle mentionnée dans la
partie 8.2.2 en utilisant les opérateurs de transfert << et >>
Grâce aux fonctions read et write, il est possible de traiter globalement un certain
nombre d’octets. Les données sont dans ce cas transférés par bloc. La syntaxe de ces deux
fonctions est la suivante
70
40
41 v . creer (); // on cée un objet
42 f l o t _ e c r i t u r e . write (( char *)& v , sizeof v ); // on écrit l ’ objet dans le fichier
43 cout < < " Autre éléve à saisir ? o / n " ;
44 rep = getche ();
45 }
46 while ( rep == ’ o ’ );
47 f l o t _ e c r i t u r e . close (); // on ferme le fichier
48 // c o n s u l t a t i o n et affichage
49 ifstream f l o t _ l e c t u r e ( nom_fichi e r ); // on ouvre le fichier
50 f l o t _ l e c t u r e . read (( char *)& v , sizeof v ); // on lit un objet
51 while ( f l o t _ l e c t u r e ) // pas fin de fichier
52 {
53 v . affiche ();
54 f l o t _ l e c t u r e . read (( char *)& v , sizeof v ); // on lit l ’ objet suivant
55 }
56 f l o t _ l e c t u r e . close ();
57 return 0;
58 }
71
72
Chapitre 9
Polymorphisme, surcharge de
fonctions
9.1 Le polymorphisme
Linguistiquement, polymorphe veut dire qui peut se présenter sous différentes formes.
Le polymorphisme est un des fondements de la programmation orientée objet.
Bien que la technique de polymorphisme puisse s’utiliser avec des fonctions n’apparte-
nant pas à des classes, elle constitue un complément fondamental à la technique d’héritage.
Elle permet de redéfinir des méthodes/données héritées de la classe mère.
de façon générale, dans une classe dérivée, on distingue trois sortes de membres (méthodes/données) :
1. Les méthodes (données) qui sont propres à la nouvelle classe : On parle alors
d’extension
(a) Ces méthodes (données) peuvent porter un nom qui n’est pas utilisée dans la
classe mère.
(b) Ces méthodes peuvent porter un nom qui est utilisé dans la classe mère avec
des paramètres en nombre et/ou en type différent : Il y a alors surcharge de la
méthode.
2. Les méthodes/données qui sont issues de la classe mère : Il s’agit alors d’héritage.
Lors de l’utilisation d’une méthode héritée sur un objet de la classé dérivée, ce
dernier est convertit implicitement en un objet de la classe mère. Par défaut, toutes
les méthodes/données de la classe mère sont héritées
3. Les méthodes/données qui redéfinissent les méthodes existantes dans la classe mère :
Il s’agit de masquage. Ces méthodes ont le même nom et le même prototype (déclaration)
que celle qu’elles redéfinissent. On dit alors que la méthode de la classe dérivée
spécialise celle de la classe mère.
73
l’extérieur de toutes les classes ont une portée globale. Si deux fonctions ont le même
nom mais des domaines de portée différents (l’une est membre d’une classe, l’autre est
membre d’une autre classe ou globale), il ne s’agit pas de surcharge de fonctions. En cas
de surcharge, les méthodes ont le même nom avec des paramètres en nombre et/ou en
type différents.
74
9.2.2 Surcharge de fonctions membre d’une classe dérivée
Exemple 9.2 (Surcharge de fonctions membres)
Remarque 9.1
Si dans le même domaine de portée, une fonction a le même nom, la même liste de
paramètres et des types différents, ceci va générer une erreur de compilation, car le com-
pilateur de saura pas à quelle fonction il est fait appel.
75
9.3 Fonctions virtuelles
Dans l’exemple du listing 9.2, la fonction affiche de la classe dérivée voiture masque
la fonction affiche de la classe mère vehicule. Toutefois, il est possible d’appeler la
fonction affiche de la classe mère en spécifiant son nom complet vehicule::affiche.
Pour la surcharge des constructeurs, voir le chapitre dédié à l’héritage.
Si un pointeur vers une classe de base est déclaré, il est possible d’instancier des objets
de toutes la hiérarchie des classe dérivées de cette classe de base. Cependant, si une
méthode de la classe de base est masquée dans les classes dérivées (la fonction garde
exactement la même signature), l’appel de cette dernière sur un des objets de la classe
dérivée invoquera toujours la méthode du même prototype de la classe de bas. Grâce aux
fonction virtuelles, le polymorphisme permet deux objet de classes différentes de réagir
différemment au même appel (fonction de même nom et signature).
76
12 {
13 matricule = n ;
14 puissance = m ;
15 }
16 virtual void affiche ()
17 {
18 cout < < " Matricule : " << matricule < < " \ n " ;
19 cout < < " Puissance : " << puissance < < " \ n " ;
20 }
21 };
22 class voiture : public vehicule
23 {
24 int nbporte ;
25 public :
26 voiture ( int n , float m , int p )
27 : vehicule (n , m )
28 {
29
30 nbporte = p ;
31 }
32 virtual void affiche ()
33 {
34 vehicule :: affiche ();
35 cout < < " nombre portes : " << nbporte < < " \ n " ;
36 }
37 };
38
39 int main ()
40 {
41 int n ;
42 float m ;
43 int p ;
44 vehicule * pv ;
45 cout < < " \ n Matricule et puissance de la voiture et nombre de portes " ;
46 cin > > n > > m > > p ;
47 pv = new voiture (n ,m , p );
48 pv - > affiche ();
49 cout < < " \ n Matricule et puissance du véhicule " ;
50 cin > > n > > m ;
51 pv = new vehicule (n , m );
52 pv - > affiche ();
53 return 0;
54 }
77
1. Pour modifier le traitement standard de la classe de base.
2. Pour compléter le traitement standard de la classe de base. La fonction de la classe
de base est alors appelée par celle de la classe dérivée.
3. Pour annuler le traitement standard de la classe de base. Elle est dans ce cas définie
avec u corps vide.
78
13 l=m;
14 }
15 friend surface operator +( surface & , surface &);
16 void afficher ()
17 {
18 cout < < " Longueur L = " <<L < < ’\ n ’;
19 cout < < " Largeur l = " <<l < < ’\ n ’;
20 }
21 };
22 surface operator +( surface & m , surface & n )
23 {
24 surface s ( m . L + n .L , m . l + n . l );
25 return s ;
26 }
27 int main ()
28 {
29 surface s1 (1 ,2);
30 surface s2 (2 ,4);
31 surface s3 = s1 + s2 ;
32 s1 . afficher ();
33 s2 . afficher ();
34 s3 . afficher ();
35 return 0;
36 }
1 Type operator op ()
op : opérateur à surcharger.
operator : mot clé.
Exemple 9.5 (Surcharge d’opérateurs)
1 # include < iostream >
2
3 using namespace std ;
4
5 class indice
6 {
7 private :
8 int n ;
9 public :
10 void set_n ( int m )
11 {
79
12 n=m;
13 }
14 int get_n ()
15 {
16 return n ;
17 }
18 indice operator ++();
19 };
20 indice indice :: operator ++()
21 {
22 ++ n ;
23 return * this ;
24 }
25 int main ()
26 {
27 indice a ;
28 a . set_n (5);
29 cout < < a . get_n () < < ’ \ n ’ ;
30 ++ a ;
31 cout < < a . get_n () < < ’ \ n ’ ;
32 return 0;
33 }
op : opérateur à surcharger.
operator : mot clé.
Exemple 9.6 (Surcharge d’opérateurs)
1 # include < iostream >
2
3 using namespace std ;
4
5 class indice
6 {
7 private :
8 int n ;
9 public :
10 void set_n ( int m )
11 {
12 n=m;
13 }
14 int get_n ()
15 {
16 return n ;
17 }
18 indice operator ++();
19 indice operator ++( int );
20 };
21 indice indice :: operator ++()
80
22 {
23 ++ n ;
24 return * this ;
25 }
26 indice indice :: operator ++( int x )
27 {
28 n ++;
29 return * this ;
30 }
31 int main ()
32 {
33 indice a ;
34 a . set_n (5);
35 cout < < a . get_n () < < ’ \ n ’ ;
36 ++ a ;
37 cout < < a . get_n () < < ’ \ n ’ ;
38 a ++;
39 cout < < a . get_n () < < ’ \ n ’ ;
40 return 0;
41 }
81
34 }
82
Deuxième partie
Travaux pratiques
83
Cette partie contient les anciens TP (avant 2017).
85
86
TP n◦ 1
Éléments de Base
1.1 Objectifs du TP
– Savoir utiliser l’environnement de programmation.
– Effectuer des entrée-sorties élémentaires.
– Savoir utiliser les opérateurs de base, déclaration et manipulation de variables.
87
1 int a , b =1;
2 a =5 + b ++;
1 int a , b =1;
2 a =5 + ++ b ;
4. Soit x,y et z trois variables entières initialisées à 1. Écrire une seule ligne de code
en C++ qui rajoute à z la somme de x et de y puis incrèmente y.
5. Écrire un programme C++ qui affiche le code ASCII d’une lettre de l’alphabet latin.
88
TP n◦ 2
Structures de Contrôle
2.1 Objectifs du TP
– Utiliser les structures de contrôle,
– Choisir la meilleure structure pour un problème donné.
89
90
TP n◦ 3
Les Tableaux
3.1 Objectifs du TP
– Manipuler des tableaux unidimensionnels.
– Lire et afficher des tableaux.
91
92
TP n◦ 4
4.1 Objectifs du TP
– Manipuler des pointeurs.
– Manipuler des structures.
– Faire le lien entre tableaux et pointeurs.
4.2.2 Exercice 2
Écrire un programme C++ qui déclare un tableau dynamique de deux dimensions en
procédant comme suit :
1. Déclarer un pointeur vers un pointeur vers un entier pp.
2. Lire le nombre de lignes n et le nombre de colonnes m du tableau dynamique.
3. Réalise une allocation dynamique avec new d’abord pour le nombre de lignes puis
pour le nombre de colonnes.
4. Lit les valeurs des éléments du tableau dynamique à partir du clavier.
5. Affiche le tableau dynamique.
93
4.3 Partie 2 : Manipulation d’une structure
Écrire un programme C++ qui :
1. Déclare une structure date qui comporte trois champs de type entier : jour, mois,
annee.
2. Déclare une structure etudiant comportant les champs suivants
– char nom[30]
– char prenom[20]
– date date naissance
3. Crée deux variables de cette structure personne1 et personne2.
4. Initialise la variable personne1.
5. Initialise la variable personne2 avec la variable personne1.
6. Modifie les champs de personne2.
7. Affiche les champs des deux variables.
94
TP n◦ 5
Les fonctions
5.1 Objectifs du TP
– Déclarer et définir des fonctions.
– Utiliser différentes techniques de passage d’arguments.
– Manipuler des pointeurs sur des structures.
95
définition de la structure et les fonctions dans un fichier d’entête séparé et l’inclure dans
l’entête.
96
TP n◦ 6
6.1 Objectifs du TP
– Mettre en pratique les notions de classe et d’objet.
– Déclarer et initialiser des objets.
– Manipuler des variables membres et fonctions membres.
97
98
TP n◦ 7
7.1 Objectifs du TP
– Mise en pratique des données et fonctions membres statiques.
– Mise en pratique de la notion de fonction amie.
– Mise en pratique de la notion de classe amie.
99
4. Calculer leurs symétriques et les associer à deux nouveaux points a1 et b1,
5. Calculer la distance par rapport à l’origine de a1 et b1 et la distance a1b1.
6. Afficher le nombre de points créés.
y=pente*x + y0 (7.3.1)
100
TP n◦ 8
Héritage
Objectifs du TP
– Mettre en pratique les notions d’héritage.
– Manipuler les classes dérivées.
101
1 nom = " nom homme " ;
2 couleury e ux = " Bleu " ;
3 age = 40;
4 poid =70
5 ismaried = true ;
102
TP n◦ 9
Polymorphisme
Objectifs du TP
– Mettre en pratique les principaux concepts du polymorphisme.
– Voir la liaison du polymorphisme avec l’héritage.
103
38 }
39 };
Écrire un programme de test qui crée deux compte, fait un dépôt sur le premier, un
retrait sur le deuxième puis un virement du premier vers le deuxième.
104
Troisième partie
Mini-projets
105
Cette partie contient les anciens Mini-projets.
107
108
Mini-projet n◦ 1
2010-2011
109
110
Mini-projet n◦ 2
2011-2012
111
4. Supprimer un client de la liste.
La liste des clients est enregistrée dans un fichier appelé ”liste clients.poc”. Toutes les
opérations citées plus haut doivent êtres enregistrées sur ce fichier.
Caractéristique Signification
ISBN Code du livre.
Titre Titre du livre.
Auteur Premier auteur du livre.
Editeur Editeur du livre.
Annee Année d’édition du livre.
Prix Prix du livre en DA.
Table 2.1 – Caractéristiques d’un livre
Caractéristique Signification
IDC Identifiant du client.
Nom Nom ou raison sociale.
Adresse Adresse du client.
Tel Numéro de téléphone du client.
Anciente Date d’inscription du client.
Table 2.2 – Caractéristiques d’un client
112
Caractéristique Signification
IDCM Identifiant de la commande.
IDCCM Identifiant du client ayant passé la commande.
Date Date de la commande.
Total Prix total de la commande.
Table 2.3 – Caractéristiques d’une commande
2.4.1 Important !
Il est impératif de respecter les points suivants :
– Écrire un code lisible, structuré et commenté.
– Réaliser une bonne analyse et organiser votre démarche avant de commencer à pro-
grammer.
– Utiliser des menus à choix multiples pour plus de convivialité. Par exemple, l’écran
d’accueil devra afficher plusieurs choix :
1. Gestion des livres.
2. Gestion des clients.
3. Gestion des commandes.
4. Quitter.
pour le choix 1, il sera possible de faire les choix suivants :
1. Afficher la liste des livres.
2. Ajouter un livre.
3. Supprimer un livre.
4. Modifier un livre.
5. Rechercher un livre.
6. Revenir au menu précédent.
113
114
Mini-projet n◦ 3
2012-2013
115
3.2.3 Gestion du calendrier
Initialement, le programmeur crée un calendrier pour un championnat donné. Il peut
toutefois le modifier au cours de la saison. Les fonctionnalités principales de cette partie
sont :
1. Ajouter une nouvelle journée.
2. Mettre à jour une journée.
3. Supprimer une journée.
3.3.1 Important !
Il est impératif de respecter les points suivants :
– Écrire un code lisible, structuré et commenté.
– Réaliser une bonne analyse et organiser votre démarche avant de commencer à pro-
grammer.
– Utiliser des menus à choix multiples pour plus de convivialité. Par exemple, l’écran
d’accueil devra afficher plusieurs choix :
1. Consulter les championnats.
2. Modifier les championnats.
3. Ajouter un nouveau championnat.
4. Quitter.
par exemeple, pour le choix 1, l’application affichera la liste des championnat disponibles,
après elle proposera les choix suivants :
116
1. Sélectionner un championnat.
2. Revenir au menu principal.
3. Quitter.
117
118
Mini-projet n◦ 4
2015-2016
119
4.2.4 Menus utilisés
L’application se présentera sous forme de menus et de sous-menus qui permettent de
réaliser les opérations citées ci-dessous, à titre d’exemple, une suggestion pour le menu
d’entrée est la suivante :
Bienvenue, saisir un numéro pour faire un choix :
1. Afficher la liste des satellites.
2. Afficher la liste des chaı̂nes.
.
3. ..
4. Quitter
4.3.1 Important !
Il est impératif de respecter les points suivants :
– Écrire un code lisible, structuré et commenté.
– Réaliser une bonne analyse et organiser votre démarche avant de commencer à pro-
grammer.
– Utiliser des menus à choix multiples pour plus de convivialité.
120
Bibliographie
[1] Y. Gerometta and J. L. Corre, C++ Le Guide Complet. Micro Applications, 2008.
[2] G. Willms, C++. PC Poche, Micro Applications, 2000.
[3] C. Delannoy, Programmer en C++. Eyrolles, 2006.
[4] C. Delannoy, Apprendre le C++. Eyrolles, 2008.
[5] S. Dupin, Le Langage C++. Le tout en poche, Campus Press, 2005.
[6] M. Nebra and M. Shcaller, Programmez avec le Langage C++. Le Livre du Zéro,
2009.
[7] N. Benabadji and N. Bechari, Guide Pratique de Programmation en C++. Houma
INFO, Editions Houma, 2009.
[8] S. Graine, Le Langage C++. L’Abeille, 2004.
[9] C. Delannoy, Exercices en Langage C++. Chihab-Eyrolles, 1993.
[10] B. Stroustrup, The C++ Programming Language. Addison-Wesley, 3rd ed., 1997.
[11] J. R. Hubbard, Theory and Problems of Programming with C++. Schaum’s Outline
Series, McGraw-Hill, 2nd ed., 2000.
121