Vous êtes sur la page 1sur 71

Cours Algorithmique Avancée

et Programmation

EILCO – ING 1

1
Algorithmique élémentaire
en C++

2
C++
•La première version de C++ a été développée en 1983
•Objectif : augmenter les possibilités du langage C (1972)
tout en conservant ses fonctionnalités, sa structure et sa
syntaxe
C++ : incrémentation de C
•Les programmes écrits en langage C sont ainsi utilisables
tels quels, pour la plupart, en C++
•Nouveau concept : la Programmation Orientée Objet

3
Entrées, sorties
•Les fonctions printf() et scanf() sont toujours disponibles, avec la
même syntaxe qu'en C, en C++
•C++ définit également les flux d'entrée et flux de sortie, gérables
par l'utilisation de cin et cout
•Exemples :
int n ;
cin >> n ; // lit une valeur entière n au clavier
cout << n ; // affiche la valeur de n à l'écran
cout << ''Hello world !'' ; // affiche Hello world ! à l'écran
•endl permet de passer à la ligne (''\n'' existe toujours) :
cout << ''Hello world !'' << endl ;
4
Entrées, sorties
•Opérateurs << et >>
int m,n ;
cin >> n >> m ; // lit deux entiers n puis m au clavier
cout << ''m vaut '' << m << '' et n vaut '' << n ;
• >> permet d'effectuer plusieurs saisies clavier dans l'ordre des
flèches. Ici, on lit au clavier n, puis m.
• Les espaces, tabulations et passages à la ligne agissent
comme séparateurs pour >>
• << permet de réaliser plusieurs affichages, en réalisant
implicitement des conversions de type

5
Entrées, sorties
•En C (ou en C++) :
int a1, a2 ; float a3;
printf("Entrez trois nombres\n");
scanf("%d %d %f", &a1, &a2, &a3);
printf(''Les nombres sont : %d, %d, %f\n'',a1,a2,a3) ;
•En C++ :
int a1, a2 ; float a3;
cout << "Entrez trois nombres" << endl ;
cin >> a1 >> a2 >> a3 ;
cout << ''Les nombres sont : '' << a1 << '', '' << a2 << '', '' << a3 << endl ;

6
Entrées, sorties
•Programme complet fonctionnel :
#include<iostream> ;
int main() {
int a1, a2, a3 ;
std::cout << "Entrez 3 nombres" << std::endl ;
std::cin >> a1 >> a2 >> a3 ;
return 0 ;
}

7
iostream
•#include<iostream> ;
•iostream est la bibliothèque standard de flux d'entrées/sorties du
langage C++. Il faut donc l'inclure pour pouvoir utiliser cin, cout
et endl (tout comme il faut inclure stdio.h pour pouvoir utiliser
printf() et scanf()).
•Les fichiers d'en-tête standard en C++ ne possèdent pas
d'extension .h (en général...)

8
Espaces de noms
•std::cout std::cin std::endl
•std est un espace de noms. C'est l'espace de noms standard,
qui contient entre autres cout, cin et endl.
•Un espace de noms est un bloc de programme (isolé par des
accolades { … }) associé à un nom.
•Exemple de définition d'un espace de noms :
namespace monespace {
//déclaration de variables, de fonctions......
}
•Il permet d'associer un nom (ici monespace) à un ensemble de
variables, fonctions... pour éviter les conflits de noms (au sens
d'identificateurs de variables). 9
Espaces de noms
Exemple :
namespace esp1 {
int n ;
}
namespace esp2 {
int n ;
}
int main(){
cin >> esp1::n ;
cin >> esp2::n ;
} 10
Espaces de noms :
using
•using namespace monespace ; permet de ne pas avoir à
préciser l'espace de noms où sont définies les variables et
fonctions que l'on veut utiliser.
•Exemple :
#include<iostream> ;
using namespace std ; // remarque : l'espace std est défini dans iostream
int main() {
int a1, a2, a3 ;
cout << "Entrez 3 nombres" << endl ;
cin >> a1 >> a2 >> a3 ;
return 0 ;
} 11
Le type booléen
•Le langage C++ définit un type booléen.
•Le type bool définit les deux valeurs true et false.
•L'opérateur de négation est !, le ou || et le et &&

bool étudiantPrésent = false ;


cout << !tb ;

12
Programmation Orientée Objet

Objets et Classes

13
Rappel : structures
•Exemple :
struct personne { // déclaration d'un canevas type
char[10] nom;
char[10] prenom;
int age;
}; // ne pas oublier le ; de fin de définition
int main(){
struct personne Pers ; // création d'une instance du canevas
Pers.nom ; // accès à un élément
}

14
Rappel : structures
•En C, on ne peut qu'accéder et modifier les éléments d'une structure, la
copier en totalité ou récupérer son adresse : il n'existe pas d'opérations sur
les structures.
•On peut définir des fonctions ayant une structure en entrée ou en sortie.

•C++ étend la notion de structure en y intégrant, en plus des éléments de


type variables (nom, prenom, age) des fonctions (par exemple une fonction
sepresenter() ).

•C++ étend cette notion de structure par la notion de classe, qu'on va étudier
par la suite.
•Une instance de classe est appelée un objet.

15
Notions du cours
•comprendre les principes des classes et des objets
•les constructeurs de classe
•attributs public protected et private
•méthodes et variables statiques et d’instances

16
Introduction aux objets
•La programmation orientée objet est une méthode qui fonde la
structure des programmes autour des objets
•Chaque objet peut être considéré comme un fournisseur de
services utilisés par d’autres objets, les clients
•Les services offerts par les objets sont :
–des données (variables) qui sont nommées attributs
–des actions (fonctions) qui sont nommées méthodes
•Un objet peut être à la fois fournisseur et client
•Important : chaque objet n’est pas décrit individuellement, la
POO fournit une construction, la classe, qui décrit les objets
possédant les mêmes propriétés

17
Classes et objets
•int i; la variable i est de type primitif entier
•Personne p; la variable p (qui est un objet) est de type
Personne (qui est une classe)
•Une classe est une combinaison de types primitifs et
éventuellement d’autres classes. Par exemple, la classe
Personne peut contenir un nom de type char[], age de type int et
la variable add de type Adresse. Adresse peut être elle-même
une classe qui contient des éléments comme : nom de rue,
numéro dans la rue,…
•Les noms de classes commencent par une majuscule
(TOUJOURS)

18
Différences classes/objets
•Les classes sont des descriptions ou encore des squelettes des
objets. Ce ne sont pas des objets en tant que tels
•Les classes sont des « moules » servant à créer des objets
•La déclaration d’une classe ne crée aucun objet
•Les objets sont créés à partir des classes, on parle alors
d’instances de classes. L’opération de création d’un objet à partir
d’une classe est aussi appelée instanciation
–Les objets (instances) créés possèdent tous les attributs et
(méthodes) de la classe dont ils sont issus
–Les objets sont différents les uns des autres (chaque personne
a a priori une adresse différente)

19
Exemple de classe
La déclaration d’une classe correspond à la déclaration d’un
nouveau type.
Par exemple, la classe Rectangle décrit des objets de type
Rectangle qui contiennent deux attributs de type réel :
•longueur et largeur

Rappel : il est d’usage de commencer les classes par une


majuscule
Rectangle
- largeur : réel
- longueur : réel

20
Instanciation d’objets
•Les attributs de l’objet prennent des valeurs initiales données
par un constructeur. Pour chaque classe, il existe un
constructeur par défaut
en pseudo-code :
variable r type Rectangle créer Rectangle()
crée une instance de la classe Rectangle avec comme
identificateur r. (cf page suivante). Les attributs sont initialisés à
0 par le constructeur.

21
Illustration
Rectangle

r largeur = 0.0
longueur = 0.0

Rectangle

r largeur = 0.0 q
longueur = 0.0

22
Les classes en C++
•L’accès aux attributs se fait en C++ par l’utilisation de la
notation pointée (depuis l'objet) ou fléchée (depuis un pointeur
sur l'objet, on y reviendra)
•L’autorisation d’accès aux attributs se fait grâce aux mots-clefs
public, protected (on y reviendra) ou private (accès restreint aux
objets de la classe)
•Par convention, l’objet courant est désigné par this, qui est une
référence (pointeur) à lui-même (nous reviendrons sur ce
concept).

23
Accès aux attributs
•L’accès à un attribut est valide si ce dernier existe, c’est-à-dire
s’il a été créé au préalable. Cet accès se fait simplement en le
nommant
•Dans une classe, toute référence aux attributs définis dans la
classe elle-même s’applique à l’instance courante de l’objet, que
l’on appelle objet courant
•L’accès aux attributs d’autres objets de fait par une notation
pointée de la forme n.a, où n est un nom qui désigne l’objet, et a
un attribut particulier
•Par défaut, nous considérons que tous les attributs d’une classe
sont privés et ne sont pas directement accessibles en dehors
de la classe. Les attributs accessibles seront explicitement
nommés public (très rare)
24
Exemple
class Rectangle {
public : déclaration explicite d’accès
double largeur, longueur ; public des attributs de la
classe Rectangle (tout ce qui
}; // ne pas oublier le ; suit cette ligne sera public)

Rectangle r;
Rectangle
+ largeur : réel
Pour accéder aux attributs : + longueur : réel
r.largeur
r.longueur

Dans notre cours, les attributs ne seront jamais publics


25
Les méthodes
Le second type de service offert par un objet à ses clients est un
ensemble d’opérations sur les attributs. Ces opérations sont
appelées méthodes.
•Pour toutes les instances d’une même classe, il n’existe qu’un
exemplaire de chaque méthode de la classe (≠ attributs)
•On peut rapprocher le principe des méthodes à des fonctions qui
ne s’appliqueraient que sur des objets d’une classe donnée
•Comme dans le cas des attributs, les méthodes peuvent être
publiques (public), protégées (protected) ou privées (private)

26
Ajout de méthodes à la classe
Rectangle
class Rectangle {
/* les attributs */
double largeur, longueur ;
public: // si rien n'est précisé, on est en private par défaut
/* les méthodes */
Rectangle
double périmètre() { - largeur : réel
return 2*(largeur + longueur) ; - longueur : réel
}
+ périmètre() : réel
double surface() { + surface() : réel
return largeur * longueur ;
}
};

27
Accès aux méthodes
•L’accès aux méthodes suit les mêmes règles que celles des
attributs
–dans la classe, toute référence à une méthode s’applique à
l’instance courante de l’objet
–depuis un autre endroit, il faut utiliser la notation pointée
•Pour rendre les méthodes accessibles aux objets d’autres
classes, il faudra les rendre publiques

exemples : calcul du périmètre du rectangle r


p = r.périmètre() ;
s = r.surface() ;
28
Surcharges de méthode
•Les méthodes peuvent avoir des en-têtes différentes bien
qu’elles aient le même nom, elles sont considérées comme
distinctes et dites surchargées
•La notion de surcharge est importante en POO
•Attention, elle peut être source d’erreurs

29
Notion de constructeur
•Un constructeur permet d'instancier des objets
•Un constructeur a le même identificateur que la classe à
laquelle il se rapporte
•En l'absence de constructeur définit dans le programme, lors de
la construction d’un objet (instanciation), les attributs sont
initialisés à des valeurs par défaut, grâce à un constructeur par
défaut
•Il est possible et très commun de redéfinir le constructeur par
défaut. On peut alors surcharger ce constructeur (et donc
disposer de plusieurs constructeurs pour une même classe).
•Exemple pour la classe Rectangle.

30
Constructeur de Rectangle
class Rectangle {
double largeur, longueur ; // attributs
public:
Rectangle() { // constructeur sans paramètre = par défaut
largeur = 1 ;
longueur = 1 ;
}
{ les méthodes}
...
};

31
suite
•Il est fréquent de proposer plusieurs constructeurs (surcharge).
Par exemple, un second constructeur pour permettre de choisir
explicitement les attributs d’un « rectangle »
Rectangle() { // constructeur n°1
largeur = 1 ;
longueur = 1 ; Rectangle
- largeur : réel
} - longueur : réel
Rectangle(double larg, lon) {
+ Rectangle()
// constructeur n°2 + Rectangle(réel,réel)
+ périmètre() : réel
largeur = larg ; + surface() : réel
longueur = lon ;
}
32
Utilisation
Rectangle r1; // utilisation du constructeur par défaut : pas de
parenthèses
Rectangle r2(3.0,2.0) ; // utilisation du constructeur 2

r1 est un rectangle de taille 1x1


r2 est un rectangle de taille 3x2

33
La classe complète en C++
class Rectangle { // les méthodes
// les attributs (privés) double perimetre(){
double largeur, longueur; return 2.0*(largeur + longueur);
}
// les constructeurs
public : double surface(){
Rectangle(){ return largeur*longueur;
largeur = longueur = 1.0; }
Rectangle
} };
- largeur : réel
- longueur : réel
Rectangle(double larg, double lon){
largeur = larg; + Rectangle()
longueur = lon; + Rectangle(réel,réel)
+ périmètre() : réel
} + surface() : réel

34
Attributs partagés
•Chaque objet possède ses propres attributs (chaque rectangle
a une largeur et longueur différentes)
•Il est possible de partager un attribut dit attribut de classe pour
toutes les instances d’une classe
–dans le cas de la classe Rectangle, un tel attribut peut être par
exemple le nombre de côtés
•Pour les différencier dans la notation UML, on les soulignera
Rectangle
•Mot clé : static
- largeur : réel
- longueur : réel
- nbCôté : entier

35
Accesseurs / Modificateurs
•En général, on évite de modifier directement les attributs à
l’extérieur du programme (c'est pourquoi ils sont privés) ;
•On utilise plutôt le principe d’encapsulation (c’est-à-dire que l’on
utilise une méthode pour positionner un attribut)
// accesseurs – modificateurs
Rectangle
public:
- largeur : réel
void changerLongueur(double lg){ - longueur : réel
longueur = lg;
} + Rectangle()
+ Rectangle(réel,réel)
void changerLargeur(double lg){ + périmètre() : réel
largeur = lg; + surface() : réel
+ changerLongueur(réel)
} + changerLargeur(réel)
double getLongueur(){ + getLongeur() : réel
return longueur; 36
}
Encapsulation
•Mécanisme de protection des membres d'un objet, en limitant
leur visibilité / accessibilité
–privé : visible de la classe (par défaut)
–publique : visible/accessible de partout
–protégé : visible de la classe et des classes enfants (on y
reviendra)

Classe

37
Notation graphique UML

38
Quelques informations sur UML
•Les classes et les instances (objets) sont représentées par des
rectangles
•Le nom des classes commence par une majuscule
•Le nom d’une instance est suivi de : et du nom de la classe est
à laquelle elle appartient, le tout est souligné

Rectangle monRectangle : Rectangle

39
Les attributs en UML
•Les attributs sont définis dans la 2ème partie du rectangle. On
fait suivre le nom de chaque attribut par : et le type de l’attribut
•un attribut précédé de + sera considéré comme public
•un attribut précédé de – sera considéré comme private
•un attribut précédé de # sera considéré comme protected
(protégé)
•un attribut statique (attribut de classe)
•sera souligné Rectangle

- largeur : réel
- longueur : réel

40
Les méthodes en UML
•La description des méthodes est réalisée dans la 3ème partie
du rectangle
•Comme dans le cas des attributs, on utilise le préfixe +,-,# afin
de décrire la visibilité de la méthode
•Chaque méthode est ensuite décrite avec sa signature
–nombre de paramètres Rectangle
–valeur (éventuelle) de retour - largeur : réel
- longueur : réel
•Les méthodes de classe
(= méthodes statiques, on y + Rectangle()
+ Rectangle(réel,réel)
reviendra) sont soulignées + périmètre() : réel
+ surface() : réel
+ changerLongueur(réel)
+ changerLargeur(réel)
41 : réel
+ getLongeur()
Créer et utiliser des objets
•Créer un nouveau dé
–De de;
•Lancement du dé (et positionnement de l’attribut valeurDe)
–de.lanceDe() ;
•Obtention de la valeur du dé
–cout << de.getValue() << endl ;
•Remarque : l'encapsulation prend ici tout son sens. Si valeurDe
était public, on pourrait modifier à l'extérieur de la fonction sa
valeur en dehors de l'intervalle [1;6]

44
Notes sur les constructeurs
•Les constructeurs sont des méthodes particulières qui ne sont
appelées que lors de la création de l’objet. Ce sont donc des
méthodes.
•Un constructeur n’a pas de type de retour, pas même void.
•Le(s) constructeur(s) a(ont) exactement le même nom que la
classe
•Les constructeurs sont en général de type public
•Les méthodes de type constructeurs ne sont jamais appelées
directement. A l’intérieur de la classe, un constructeur peut
appeler un autre constructeur en utilisant le mot-clef this :
(*this)=Rectangle();

45
Constructeur de copie
•En plus du constructeur par défaut vu précédemment, toute
classe possède un constructeur de copie.
•Ce constructeur permet de créer un nouvel objet identique à un
objet existant. Il aura pour identificateur le nom de la classe,
n'aura pas de type de retour (comme tout constructeur) et
prendra un seul paramètre d'entrée : l'objet à copier.
•Utilisation :
Rectangle r ; // création d'un objet r
Rectangle rcopie(r) ; // création d'un objet rcopie possédant les
mêmes attributs que r
Rectangle rcopie2 = r ; // rcopie2 est une copie de r par utilisation
implicite du constructeur de copie

46
Constructeur de copie
•Le constructeur de copie existe toujours, il n'a pas à être écrit ou
redéfinit (à l'inverse du constructeur par défaut, qui doit être redéfinit
dès qu'un autre constructeur est écrit).
•On peut cependant le redéfinir comme suit :
Rectangle(Rectangle const& rect){
… // instructions de copie et autres instructions éventuelles
}

47
class De{ Il y a ici deux constructeurs pour la classe De
int valeurDe; (plus le constructeur de copie).
public:
De(){ Le premier redéfinit le constructeur par défaut.
lanceDe();
} Dans le deuxième constructeur, value est le
De(int value){ paramètre formel qui sera affecté à l’attribut
valeurDe = value; valeurDe
}
void lanceDe(){
srand (time(NULL));
valeurDe = rand()%6 + 1;
}
int getValue(){
if(valeurDe >=1 && valeurDe <=6){
return valeurDe;
} else {
return -1;
}
}
};

48
Exemple d’utilisation des
De d1(3);
constructeurs
cout << d1.getValue() << endl ;
De d2 ; // appel au constructeur par défaut
cout << d2.getValue() << endl ;
for(int i = 0; i<50; i++){
d2.lanceDe();
cout << d2.getValue() << endl ;
}
De d3(d2);
d2=d1; // d2.valeurDe est maintenant égal à d1.valeurDe
•Nous créons trois dés d1, d2 et d3 par l’utilisation de nos trois
constructeurs différents
•L'appel au constructeur par défaut (sans paramètres) se fait sans
indiquer les parenthèses
49
Surcharge d'opérateurs
•Grâce au constructeur de copie, on peut utiliser l'opérateur = pour des
objets.
•On a déjà vu la surcharge de constructeurs, la surcharge de méthodes, il
existe également en C++ la surcharge d'opérateurs : elle permet d'associer
aux opérateurs classiques ( + - * / < > >= <= == ... ) des chaînes d'instructions
propres à la classe dans lesquels ils sont écrits.
•Exemples en C++, pour une classe Maclasse :
bool operator== (Maclasse const& a, Maclasse const& b) { …... }
Maclasse operator+ (Maclasse const& a, Maclasse const& b) { …... }
•operator+ est un nom de fonction qui indique que l'on va définir comment
utiliser + avec des objets de Maclasse.
•Elle a des entrées (de type objet) et des sorties (booléens pour des
comparaisons, objets pour des opérations mathématiques).
•Elle est définie par une suite d'instructions (à écrire)
•const& assure que les entrées ne seront pas modifiées pour le reste du
programme. 50
Surcharge d'opérateurs :
comparaison (exemple de ==)
•Supposons que Maclasse n'a qu'un attribut : att1
bool operator== (Maclasse const& a, Maclasse const& b) {
if (a.att1==b.att1) return true ;
else return false ;
}
•Cette fonction compare en fait les attributs des objets en entrée.
•Cette fonction s'écrit en dehors de la classe. On a donc besoin ici que
att1 ait été déclaré public. Si att1 est privé, on doit utiliser un accesseur
(principe de l'encapsulation) constant (ne modifiant pas l'objet).
•Utilisation :
Maclasse obj1 ; Maclasse obj2 ;
cout << (obj1==obj2) << endl ;

51
Surcharge d'opérateurs :
arithmétique (exemple de +)
•Supposons toujours que Maclasse n'a qu'un attribut : att1
Maclasse operator+ (Maclasse const& a, Maclasse const& b) {
Maclasse c ;
c.att1=a.att1+b.att1 ;
return c ;
}
•Utilisation :
Maclasse obj1 ; Maclasse obj2 ;
Maclasse obj3 = obj1+obj2;
•On peut également définir l'opérateur +=, qui aura pour en-tête :
void operator+= (Maclasse const& a)
•Cet opérateur pourra être définit comme étant une méthode de la classe
Maclasse. Il aura donc toujours accès aux attributs de la classe.
52
Surcharge d'opérateurs :
opérateurs de flux (ex : <<)
•Permet d'afficher un objet d'une manière prédéfinie :
•Rectangle r ;
•cout << r ; // affichera par exemple ''Rectangle de taille 3x6''
•En TP

53
Attributs d’instances
•dans la classe De, la variable valeurDe est une variable
d’instance
•Cela signifie que l'attribut valeurDe est créé pour chaque objet
de type De.
•Si on crée 10 objets de type De, on créera 10 variables
valeurDe (qui auront des valeurs a priori différentes)

54
Attributs de classe (ou
partagés)
•Les attributs de classe sont associés à la classe et non
individuellement aux objets de la classe et sont partagés par
toutes les instances de la classe
•on utilise le mot-clef static devant un attribut pour indiquer qu’il
est partagé par toute la classe
•L'initialisation des attributs statiques se fait en dehors de la
classe sous la forme (exemple d'un entier initialisé à 0) :
int Maclasse :: monattribut = 0 ;
•quelques exemples d’attributs statiques (ou partagés) :
–nombre d’objets créés depuis la classe (très classique – cf
exercice)
–constantes (valeur max et min d'un dé par exemple)
55
–variables globales utilisées par les objets
Méthodes d’instances / de
classes
•Comme pour les attributs, il est possible d’avoir des méthodes
d’instance ou de classe
•Une méthode de classe est appelée sur la classe et non sur les
objets (sa réalisation est indépendante d'un objet particulier)
•Elle est introduite comme pour un attribut de classe par le mot-
clef static. Pour l’appeler, on appelle le nom de la classe suivi du
nom de la méthode.

56
Exercice : réécriture de la
classe De
•ajouter une variable d’instance à la classe De : nombreDeFaces
•Cela signifie que chaque dé peut avoir un nombre de faces
différent
•Nous ajoutons une constante : NOMBRE_FACES_DEFAUT
•Si on utilise le constructeur par défaut et que l’on ne précise pas
le nombre de faces, le nombre de faces par défaut vaudra
NOMBRE_FACES_DEFAUT
•On ajoutera l'opérateur == qui vérifiera l’égalité de deux dés

57
De : classe existante
class De{
int valeurDe; •ajouter une variable d’instance à la classe De : nombreDeFaces
public: •ajouter une constante : NOMBRE_FACES_DEFAUT
De(){ •ajouter l'opérateur ==
lanceDe(); •modifier les méthodes en fonction de ces ajouts
}
De(int value){
valeurDe = value;
}
void lanceDe(){
srand(time(NULL)) ;
valeurDe = rand() % 6 + 1;
}
int getValue(){
if(valeurDe >=1 && valeurDe <=6){
return valeurDe;
} else {
return -1;
}
}
58
};
De : classe complète
class De{ int getValue() const {
int valeurDe; if(valeurDe >=1 && valeurDe <=nbFaces){
int nbFaces; return valeurDe;
static const int NbFacesDefaut=6; } else {
public: return -1;
De(){ }
nbFaces = NbFacesDefaut; }
lanceDe(); };
} bool operator== (De const& d1, De const& d2) {
De(int faces){ if (d1.getValue()==d2.getValue()) return true ;
nbFaces = faces; else return false ;
lanceDe(); }
}
De(int faces, int value){ Remarque : l'accesseur getValue() doit être
nbFaces = faces; spécifié comme ne modifiant pas l'objet
valeurDe = value; (mot-clé const) pour pouvoir être utilisé dans
} operator==
void lanceDe(){
srand(time(NULL)) ;
valeurDe = rand() % nbFaces + 1;
} 59
Les tableaux en C++ (vector)
• La syntaxe du langage C est toujours disponible. On parle de
tableaux statiques : leur taille est fixée à la déclaration.
• C++ permet également de déclarer des tableaux dynamiques,
dont la taille peut changer en cours de programme. C'est le but
de la classe vector
#include<vector>
• Déclaration d'un tableau dynamique tab d'entiers, vide :
vector<int> tab;
• Déclaration d'un tableau dynamique tab de 10 entiers :
vector<int> tab(10);
• Déclaration d'un tableau dynamique tab de 10 entiers tous
égaux à 0 :
vector<int> tab(10,0); 60
#include<vector> vector
vector<int> tab(10,0);
• Accès aux éléments d'un tableau dynamique : comme pour un
tableau statique :
tab[5] ; // accès à l'élément numéro 5 (le 6eme)
for(i=0;i<10;i++) { tab[i] ; } // accès à tous les éléments
• Ajout d'élément (et donc incrémentation de la taille) :
tab.push_back(3) ; // ajoute l'entier 3 à la fin du tableau (en tab[10])
• Suppression d'élément (et donc diminution de la taille) :
tab.pop_back() ; // supprime le dernier élément
• Récupération de la taille du tableau :
tab.size() ; // retourne la taille du tableau (après toutes ces lignes : 10)
• Les fonctions de vector gèrent seules les allocations
dynamiques de mémoire
• vector peut lister des objets : vector<De> 61
Les chaînes de caractères en C++
(string)
• En langage C, on utilise des tableaux de caractères pour définir les
chaînes de caractères
• En C++, en plus des tableaux de caractères, on peut utiliser la
classe string
#include<string>;
• Exemple :
string phrase = "Hello World !" ; // ou string phrase(''Hello World !'') ;
cout << phrase << endl;
phrase = "Bonjour Monde !"; // remarque : longueur différente
cout << phrase << endl;
• La classe string facilite grandement l'utilisation des chaînes de
caractères
62
string
• Quelques méthodes et opérateurs :
string phrase = ''Hello'' ;
string phrase2 = ''World !'' ;
string phrase3 = phrase + phrase2 ; // concaténation
phrase==phrase2 ; // comparaison
phrase<phrase2 ; // comparaison (alphabétique)
phrase.size() ; // taille de la chaîne (pas de \0)
phrase3.substr(2,5) ; // retourne une sous-chaîne à partir de
l'élément 2, sur 5 caractères

63
string
• Quelques méthodes et opérateurs :
string phrase = ''Hello'' ;
string phrase2 = ''World !'' ;
string phrase3 = phrase + phrase2 ; // concaténation
phrase==phrase2 ; // comparaison (ici : false)
phrase<phrase2 ; // comparaison (alphabétique) (ici : true)
phrase.size() ; // taille de la chaîne (pas de \0) (ici 5)
phrase3.substr(2,5) ; // retourne une sous-chaîne à partir de
l'élément 2, sur 5 caractères (ici :
''lloWo'')

64
Le pointeur this
• Toutes les classes disposent du pointeur this, qui pointe vers
l'objet actuel
exemple :
De(int nombreDeFaces){
this->nombreDeFaces = nombreDeFaces;
}
• Il y a deux variables nombreDeFaces
–nombreDeFaces correspond au paramètre formel
–this->nombreDeFaces correspond à la variable d’instance
• La flèche -> correspond au . permettant d'accéder aux attributs et
méthodes, mais pour les pointeurs.
• On pouvait aussi écrire (*this).nombreDeFaces
65
Exercice-résumé : classe Etudiant
• Attributs d'une classe Etudiant (privés)
–nom, prénom : chaînes de caractères string
–année (de naissance) : entier
–tableau dynamique de notes tabnotes : vector<double>
• Deux constructeurs (publics)
–un avec nom, prénom
–un avec nom, prénom et année de naissance
–les constructeurs initialiseront tous le tableau de notes comme
étant de taille 0
• Méthodes (publiques)
–moyenne() : pour calculer la moyenne des notes
–max() qui retournera la meilleure note
66
–min() qui retournera la note la plus faible
Exercice-résumé : classe Etudiant
–GetNom(), getPrenom() et anneeNaissance() : accesseurs sur les attributs de
nom, prénom et année de naissance
–ajouterNote(double n) : pour ajouter la note n à l’étudiant et
afficher la nouvelle moyenne de l'étudiant
• Programme principal : crée deux étudiants et dit lequel est le plus
vieux
• Attribut de classe (static) : nombre d'instances de la classe
Etudiant

• Représenter la classe en diagramme UML


• Écrire la classe complète (en C++)

67
Diagramme UML d'Etudiant
Etudiant

- nom, prenom: string


- annee : int
- tabNotes : vector<double>
+ nbInstances : int

+ Etudiant(n: string, p: string)


+ Etudiant(n : string, p: string,année : int)
+ moyenne() : double
+ max() : double
+ min() : double
+ getNom() : string
+ getPrenom() : string
+ anneeNaissance() : int
+ ajouterNote(note : double)
68
class Etudiant {
Classe étudiant
double moyenne(){
int annee;
double m=0;
string nom, prenom;
int i;
vector<double> tabNotes;
for (i=0;i<tabNotes.size();i++) {
static int nbInstances;
m=m+tabNotes[i];
public:
}
Etudiant(string n, string p){
return m/tabNotes.size();
nom=n;
}
prenom=p;
double min(){
nbInstances++;
double m=tabNotes[0];
}
int i;
Etudiant(string n, string p, int an){
for (i=1;i<tabNotes.size();i++) {
nom=n;
if (tabNotes[i]<m) m=tabNotes[i];
prenom=p;
}
annee=an;
return m;
nbInstances++;
}
}
69
Classe étudiant
double max(){ void ajouterNote(double note){
double m=tabNotes[0]; tabNotes.push_back( note );
int i; cout << " Nouvelle moyenne de " << prenom <<
for (i=1;i<tabNotes.size();i++) { " " << nom << " : " << moyenne() << endl;
if (tabNotes[i]>m) m=tabNotes[i]; }
} };
return m;
} int Etudiant::nbInstances=0 ; // les attributs statiques
double getNom(){ s'initialisent en dehors de la classe. Cette initialisation
return nom; est possible même si l'attribut est privé (par contre on ne
} pourra pas y accéder dans le main() par exemple)
double getPrenom(){
return prenom;
}
int anneeNaissance(){
return annee;
} 70
Programme principal
int main() {
Etudiant e1 ("Deuf","John",1965);
Etudiant e2 ("Defer","Phil",1982);
int an1=e1.anneeNaissance();
int an2=e2.anneeNaissance();
if (an1>an2)
cout << e1.getPrenom() << " " << e1.getNom() << "est l'étudiant le plus vieux" <<
endl;
else
cout << e2.getPrenom() << " " << e2.getNom() << "est l'étudiant le plus vieux" <<
endl;
return 0;
}

71

Vous aimerez peut-être aussi