Académique Documents
Professionnel Documents
Culture Documents
Informatique 5: Programmation
Orientée objet en Langage C++
Filière: SMI
Semestre: 5
Année universitaire: 2022-2023
1
04/12/2023
Contenu
Généralités
Classe et Objets
L’encapsulation
L’héritage
Le polymorphisme
• 3ème langage le plus utilisé au monde pour les applications Android et le 2eme pour
l’intelligence artificielle après Python (classements 2022,
https://fr.yeeply.com/blog/langages-programmation-plus-utilises-developpeurs-2022/)
• JVM(hotspot) et une partie du noyau de Google Chrome écrits en C++
• Première version développée par Bjarne Stroustrup de Bell Labs AT&T en 1980
Appelé à l’origine « Langage C avec classes »
• Devenu une norme ANSI/ISO C++ en juillet 1998 (C++98 - ISO/IEC 14882) – mise à
jour en 2003 (C++03)
- ANSI : American National Standard Institute
- ISO : International Standard Organization
2
04/12/2023
Gestion de la mémoire :
• Java :
• Création des objets par allocation dynamique (new)
• Accès aux objets par références
• Destruction automatique des objets par le ramasse miettes
• C++ :
• Allocation des objets en mémoire statique (variables globales), dans la pile (variables
automatiques) ou dans le tas (allocation dynamique),
• Accès direct aux objets ou par pointeur ou par référence
• Libération de la mémoire à la charge du programmeur dans le cas de l'allocation
dynamique
• Autres possibilités offertes par le C++ :
Variables globales, compilation conditionnelle (préprocesseur), pointeurs, surcharge des
opérateurs, patrons de classe template et héritage multiple.
3
04/12/2023
1- Introduction
- Caractéristiques du langage C++
Apparu au début des années 90, le langage C++ est actuellement l’un des plus utilisés
dans le monde, aussi bien pour les applications scientifiques que pour le développement
des logiciels
C++ =langage C (Structuré) +POO (orientée objet)+(gestion des exceptions) .
Le C++ est une surcouche de C, avec quelques incompatibilités de syntaxe
Un programme C est la plupart du temps un programme C++.
Exemples:
int n ;
….
n=… ;
….
int q=2*n-1 ;
….
for (int i=0 ;i<n ;i++) // en C: int i; for (i=0 ;i<n ;i++)…
4
04/12/2023
Syntaxe:
- cout<<expression1 <<expression2<<…..<<expressionN;
affiche sur l’écran les valeurs des différentes expressions. Les expressions peuvent être des chaines de
caractères ou bien des variables
Remarque :
Toute la bibliothèque standard C++ est définie dans son propre espace de nom, le namespace std. Ainsi, il est
possible de faire appel directement à tous les éléments issus de la bibliothèque <iostream> sans utiliser le
préfixe std::
#include <iostream>
using namespace std ;
int main() {
cout << "Hello World" << sendl;
}
5
04/12/2023
Espaces de noms
• Utilisation d’espaces de noms (namespace) lors de l’utilisation de nombreuses bibliothèques pour
éviter les conflits de noms.
• Espace de noms : association d’un nom à un ensemble de variable, types ou fonctions
Ex. Si la fonction MaFonction() est définie dans l’espace de noms MonEspace, l’appel
de la fonction se fait par:
MonEspace::MaFonction()
• Pour être parfaitement correct :
std::cin
std::cout :: opérateur de résolution de portée
std::endl
• Pour éviter l’appel explicite à un espace de noms : using
using std::cout ; // pour une fonction spécifique
using namespace std; // pour toutes les fonctions
Exemple:
#include <iostream>
using std::cout;
using std::endl;
int main() { // si on veut utiliser cin par exemple, il faudra écrire std::cin
cout << "coucou" << endl;
}
• Types dérivés
En C++, on définit comme en C des structures. Mais, dans la déclaration d’objets
de ces types dérivés, les mots clés struct, ne sont plus nécessaires ;
Exemple :
struct assure{ … } ;
main() {
const int n=50 ;
Float x=23,44;
assure a[n] ; //en C struct assure a[n] ;
}
6
04/12/2023
Remarque:
Le C++, contrairement au C, autorise, dans une certaine mesure, le non-respect du type des arguments lors d’un
appel à fonction: le compilateur opère alors une conversion de type.
Exemple:
double ma_fonction(int u, float f) { return (u*f); }
int main() { char c; int i, j; float r; double r1, r2, r3, r4;
r1 = ma_fonction( i, r ); // appel standard
r2 = ma_fonction( c, r); // appel correct, c est converti en int
r3=ma_fonction( i, j); // appel correct, j est converti en float
r4 = ma_fonction( r, j); // appel correct, r est converti en int // et j est converti en float
return 0;
}
7
04/12/2023
Exercice d’application :
Ecrire la fonction float developpementExp(float x,int n) qui
𝑛
calcule et renvoie le résultat.
𝑥𝑖
𝑖!
𝑖=0
Ecrire la fonction principale et mettre en œuvre la fonction précédente en utilisant les propriétés de conversion de
type.
b- Fonctions
- Arguments par défaut:
Une valeur fournie dans une déclaration de fonction est automatiquement affectée
par le compilateur si la fonction appelante ne fournit pas de valeur pour
l’argument.
Exemple :
int sum(int x, int y, int z = 0, int w = 0) { //les deux attributs z et w ont comme valeur par
défaut zéro
return (x + y + z * w);
}
int main() {
cout << sum(10, 15) << endl; // affiche: 25
cout << sum(10, 15, 25) << endl; // affiche: 25
cout << sum(10, 15, 25, 3) << endl; // affiche: 100
return 0;
} B.M Cours C++ 16
8
04/12/2023
c- Surcharge de fonctions :
• La surcharge de fonctions est une fonctionnalité qui permet de définir, dans le même
programme, deux fonctions ou plus avec le même nom mais elles diffèrent par le type ou le
nombre des paramètres et aussi par le type de passage d’argument (par valeur , par référence
• La surcharge de fonctions peut être considérée comme le polymorphisme en C++.
Exemple 1:
#include <iostream>
using namespace std;
void afficher(int i) { cout << " passage par valeur de type int :" << i << endl; }
void afficher(int &a) { cout << " passage par référence de type int :" << a << endl; }
void afficher(char *c) { cout << " La valeur est de type char* :" << c << endl; }
int main( ) {
char s[12];
afficher(5);
afficher(33);
afficher(s);
return 0;
}
Exemple 2:
#include <iostream>
using namespace std;
void essai(float x,char c,int n=0){
cout<<"Fonction N°1: x = "<<x<<" c = "<<c<<" n = "<<n<<"\n";}
void essai(float x,int n){
cout<<"Fonction N°2: x = "<<x<<" n = "<<n<<"\n";}
int main(){
char l='z';int u=4;float y = 2.0;
essai(y,l,u); // fonction N°1
essai(y,l); // fonction N°1
essai(y,u); // fonction N°2
essai(u,u); // fonction N°2
essai(u,l); // fonction N°1
//essai(y,y); rejet par le complateur
essai(y,y,u); // fonction N°1
return 0;
}
9
04/12/2023
Remarques:
• Des précautions doivent être prises lors de l’utilisation de delete.
• Lorsque qu’un pointeur ptr a été alloué par new, on écrira alors delete ptr pour le libérer.
• delete ne doit pas être utilisé pour des pointeurs déjà détruits.
• delete ne doit pas être utilisé pour des pointeurs obtenus autrement que par l’utilisation de new.
• Une fois un pointeur détruit, on doit évidement arrêter de l’utiliser.
fuite de mémoire:
Chaque allocation avec "new" doit impérativement être libérée (détruite) avec "delete" sous peine de créer une
fuite de mémoire.
La fuite de mémoire est une zone mémoire qui a été allouée dans le tas par un programme qui a omis de la
désallouer avant de se terminer.
Cela rend la zone inaccessible à toute application (y compris le système d’exploitation) jusqu’au redémarrage du
système.
Si ce phénomène se produit trop fréquemment la mémoire se remplit de fuites et le système finit par tomber
faute de mémoire.
10
04/12/2023
Exercice
Ecrire le programme suivant (correcte en C et en C++) en utilisant les nouvelles possibilités
d’entrées/sorties de C++ (en évitant l’utilisation des fonctions printf, scanf et malloc) :
#include<stdio.h>
int main(){
int n,i; float s,*b;
printf("Entrer un entier \n ");
scanf("%d ",&n);
b=(float *)malloc(sizeof(float)*5);
for(int i=0;i<n;i++){
scanf("%f",b+i);
s+=*(b+i);}
printf("la somme des nombres est: %f \n",s);
for(int i=0;i<n;i++)
printf(", %f",*(b+i));
free(b);
return 0;
}
B.M Cours C++ 21
11
04/12/2023
Variables statiques
Variables statiques dans une fonction doivent être initialisées à l'intérieur des fonctions membres et leur portée est réduite à
celle du bloc dans lequel elles ont été déclarées.
Exemple:
using namespace std;
void compteur(){
static int count = 0;
cout << count << ", ";
count++;
}
int main() {
for (int i=0; i<5; i++)
compteur();
return 0;
}
Résultat: 0, 1, 2, 3, 4, 5, 6, 7,
12
04/12/2023
Définition: rappel
Classe :
• Regroupement de données (attributs ou champs) et de méthodes (fonctions
membres)
• Extension des structures (struct) avec différents niveaux de visibilité (protected,
private et public)
13
04/12/2023
- Déclaration :
c’est la partie interface de la classe(définition abstraite). Elle se fait dans un fichier dont le nom se
termine par .h. Ce fichier se présente de la façon suivante :
class Maclasse {
private:
déclarations des données et le prototype des fonctions-membres privées
protected:
déclarations des données et le prototype des fonctions-membres visibles en interne
et par les objets des classes dérivées
public:
déclarations des données et le prototype des fonctions-membres publiques
};
class Ellipse {
Vision private :
float m_cX, m_cY;
Exemple: interne float m_a, m_b;
Vision public :
externe void deplace(float dx, float dy);
void zoom(float z);
float surface();
};
- Définition :
c’est la partie implémentation de la classe( définition du code complet des différentes fonctions-
membres de de la classe). Elle se fait dans un fichier dont le nom se termine par .cpp
Exemple:
14
04/12/2023
- Utilisation :
elle se fait dans un fichier dont le nom se termine par .cpp dans le quel on crée les objets de type classe et
faire l’appel au différentes fonctions.
Exemple:
Ecllipse a, b[ ];
On peut accéder à n’importe quel membre public (donnée ou fonction) d’une classe en utilisant
l’opérateur (.)
Exemple:
Exemple:
//Déclaration
class points {
protected :
float x, y;
public :
points(float z);
void affichage(float d);
void affichage();
};
//Définition
void points::affichage(float d){ std::cout<<"la surface de l'ellipse est: "<<d;}
void points::affichage(){ std::cout<<" x= "<<x<<" y= "<<y<<endl; }
points::points(float a){ x= a; y= a;}
//Utilisation
int main() {
points *e=new points(3);
points *ee[3];
for( int i=0;i<3;i++) ee[i]=new points((float)i);
for( int i=0;i<3;i++) ee[i]->affichage();
delete e;
delete ee[3];
return 0;
}
15
04/12/2023
Main.cpp
#include "defclasse1.h"
#include "defclasse2.h"
Void main() { <------ Utilisation
………………..
}
Remarque :
la directive d’inclusion #include permet d’inclure un fichier de déclarations dans un autre fichier:
#include <fichier_standard> fichier avec le compilateur C++,
#include "untel.h" , s’il s’agit d’un fichier écrit par nous-mêmes.
Par convention, les noms des classes commencent par une majuscule, les données membres par _ ou
m_, les fonctions membres par une minuscule.
16
04/12/2023
• Constructeurs
• De même nom que le nom de la classe
• Définition de l'initialisation d'une instance de la classe
• Appelé implicitement à toute création d'instance de la classe
• Méthode non typée, pouvant être surchargée
• Elle peut recevoir zéro, un ou plusieurs arguments
• Destructeur
• De même nom que la classe mais précédé d'un tilde (~)
• Définition de la désinitialisation d'une instance de la classe
• Appelé implicitement à toute disparition d'instance de la classe
• Méthode non typée et sans paramètre
• Ne pouvant pas être surchargé
17
04/12/2023
Exemple à tester:
class points {
private : float x;
public :
float y;
points(float z=19,float a=32);
void affichage(float d);
void affichage();
void setx(float z);
};
void points::setx(float z){x=z;}
void points::affichage(float d){ std::cout<<"la surface de l'ellipse est: "<<d;}
void points::affichage(){ std::cout<<"x= "<<x<<" y= "<<y<<endl; }
points::points(float a, float b){ x= a; y= b; }
int main() { points p1; points p(11);
points pp(32,21);
p1.affichage();
p.y=500; p.setx(222); p.affichage();
pp.affichage(); return 0;
}
B.M Cours C++ 35
Exercice :
Ajouter à l’exemple précédent, les deux méthodes suivantes:
- La méthode distance(points p) qui permet de calculer la distance entre deux points
- La méthode deplacer(float dx=0,float dy=0) pour déplacer un point selon l’axe des x et/ou des y.
- Ecrire la fonction principale main
18
04/12/2023
Constructeur de recopie
De la même manière que l'affectation (par défaut), le constructeur de recopie par défaut effectue la
copie membre à membre de la source vers la destination.
Il est appelé dans trois situations:
- Création d'un nouvel objet initialisé comme étant une copie d'un objet existant:
points p(2, 5);
Points pc(p); // création de l'objet pc image à l’objet p
- Ou bien
Points pc=p; // création de l'objet pc une copie de p.
- Ou bien
Points pc; // création de l'objet.
pc=p;
#include <iostream>
#include <math.h>
using namespace std;
class points {
private :
float x, y;
public :
points(float z);
points();
void affichage(string s);
float distance(points p);
void deplacer(float dx, float dy);
};
void points::affichage(string s){ std::cout<<s<<"x= "<<x<<" y= "<<y<<endl; }
points::points(float a){ x= a; y= a; }
float points::distance(points a){ return sqrt((a.x-x)*(a.x-x)+(a.y-y)*(a.y-y));}
void points::deplacer(float dx=0, float dy=0){ x=x+dx; y=y+dy;}
points::points(){}
int main() {
points p(2); p.affichage("p ");
points pc1(p);
points pc2; pc2=p;
pc2.deplacer(2,11);
points pc3=p;
p.deplacer(3,33);
p.affichage("p après modification "); pc1.affichage("pc1 "); pc2.affichage("pc2 "); pc3.affichage("pc3 ");
return 0;
}
19
04/12/2023
Destructeurs
Le destructeur est une fonction membre systématiquement exécutée «à la fin de la vie » d’un
objet statique, automatique, ou dynamique. On ne peut pas passer de paramètres par le
destructeur.
Exemple:
Un destructeur de la classe points pourrait se déclarer par :
public:
~points ( ) ;
Exemple :
#include <iostream>
#include <math.h>
using namespace std;
class points {
private : float x, y;
public :
points(float z);
points();
~points();
void affichage(string s);
void deplacer(float dx, float dy);
};
points::~points(){cout<<"destriction des objets x= "<<x<<" y= "<<y<<endl; }
void points::affichage(string s){ std::cout<<s<<"x= "<<x<<" y= "<<y<<endl; }
points::points(float a){ x= a; y= a; }
void points::deplacer(float dx=0, float dy=0){ x=x+dx; y=y+dy;}
points::points(){}
int main() {
points p(2); p.affichage("p ");
points pc1(p);
points pc2; pc2=p;
pc2.deplacer(2,11);
points pc3=p;
p.deplacer(3,33);
p.affichage("p après modification "); pc1.affichage("pc1 "); pc2.affichage("pc2 "); pc3.affichage("pc3 ");
return 0;
}
20
04/12/2023
Classe canonique
On appelle une classe canonique toute classe qui contient au moins les éléments suivants :
- Au moins un constructeur régulier
- Un constructeur de recopie
- Un destructeur
- Un opérateur d'affectation
class point{ // membres privés
public: point(…); // un constructeur régulier
point(const point&); //un constructeur de recopie
~point(); // un destructeur
Point &operator=(const point&); // opérateur d'affectation
};
• L’opérateur this
Une méthode reçoit toujours implicitement en argument l’adresse de l’objet de sa
classe qui l’a appelée.
Ainsi, pour : pt.affiche() ;
L’adresse de pt est transmise en argument à la fonction affiche. Dans la fonction,
le pointeur sur l’objet qui l’a appelée est désigné par le mot clé this
Exemple pour la classe point déjà définie, les coordonnées de l’objet qui fera
l’appel sont:
x et y ou this->x et this->y
class points {
Exemple d’utilisation pour la classe point
private :
float x, y;
public :
points(float a, float b=2){ x= a; y= b; }
void affichage(string s);
void copier( points p){ this->x+=p.x; this->y+=p.y; }
};
void points::affichage(string s){ cout<<s<<"x= "<<this->x<<" y= "<<this->y<<endl; }
int main() {
points p(2,3); p.affichage("p ");
points pp(4,3); pp.copier(p); pp.affichage("copie ");
return 0;
} B.M Cours C++ 42
21
04/12/2023
Une méthode peut être surchargée comme toute fonction ordinaire en C++.
Dans la surcharge de fonction, la fonction est redéfinie en utilisant différents types
d’arguments ou un nombre différent d’arguments.
Ce n'est que par ces différences que le compilateur peut différencier les fonctions.
L'avantage de la surcharge de fonctions est qu'elle augmente la lisibilité du
programme car il n'est pas nécessaire d'utiliser des noms différents pour la même
action.
Exemple 1 :
Supposons que nous voulions créer une seule fonction moyenne, pouvant gérer la moyenne de 2
nombres, 3 nombres de types différents, nous ne pouvons le faire qu'en utilisant la surcharge de
la fonction
class Utilitaire {
public:
static float moyenne(int a,int b);
static float moyenne(float a,float b);
static float moyenne(int a,int b,int c);
};
float Utilitaire::moyenne(int a,int b){
return (a+b)/2.0;
}
float Utilitaire::moyenne(float a, float b){
return (a+b)/2;
}
float Utilitaire::moyenne(int a, int b, int c){
return(a+b+c)/3.0;
}
int main() {
cout << "Moyenne (3,4) = " << Utilitaire::moyenne(3, 4) << endl;
cout << "Moyenne (3,4,6) = " << Utilitaire::moyenne(3, 4, 6) << endl;
cout << "Moyenne (6.4,1.25) = " << Utilitaire::moyenne(6.4f, 1.25f) << endl;
return 0;
}
22
04/12/2023
Exercice 1 :
Créer une classe vecteur3d pour représenter un vecteur dans l’espace caractérisé par
ses coordonnées x, y et z,
La classe comporte :
- un constructeur d’initialisation d’un vecteur
- Un destructeur qui affiche un message après la suppression de chaque objet.
- une méthode d’affichage d’un vecteur
- Une méthode qui retourne la norme d’un vecteur (float NormeVect())
- Une méthode qui retourne la somme de deux vecteurs (vecteur3d SommeVect(
vecteur3d v))
- Ajouter une méthode de classe qui effectue elle aussi la somme deux vecteurs.
Écrire un programme principal de test qui crée deux vecteurs, les afficher, calculer et
afficher la norme d’un vecteur, calcule et affiche la somme deux vecteurs.
Fonctions Amies
Déclaration d’amitié
Il peut arriver qu’une fonction n’appartient pas à une classe ait besoin d’accéder à des
données de cette classe. Une façon de procéder serait de déclarer ces données
publiques, mais cela est contradictoire avec la notion de classe, dans la mesure où
l’un des intérêts de l’utilisation des classes est justement de protéger les données.
23
04/12/2023
Exercice :
Soit une classe point qui comporte comme membres donnés les coordonnées du point
dans le plan, et comme membres fonctions le constructeur et une fonction affiche..
Ajouter une fonction externe amie de la classe point, qui reçoit deux arguments de type
point et renvoie un boolean qui vaut true si les deux points coïncident et false si non.
Ecrire un programme principal d’essai
24
04/12/2023
Exemple :
Redéfinition de l’opérateur + : Le nom de la
la fonction est déclaré par : fonction
type operator + (arguments) {
……..
}
25
04/12/2023
exemple:
Opérateur d'affectation =
Un opérateur d'affectation sert donc à l'affectation dans une expression et, retourne
une référence. La signature de cet opérateur est comme suit :
objy& operator=(objx)
Ceci est équivalent d'écrire :
y=x ou bien y.operator=(x)
Exemple:
using namespace std;
class points {
private :
public : float x, y;
points(float a, float b=2){ x= a; y= b; }
points::points(float a)
int main() {
points p(2);
p.affichage("p ");
points pp(3); pp+=p;
pp.affichage("pp ");
int i= pp==p;
if (i==0) cout <<"les deux points sont confondus ";
else cout <<" les deux points ne sont pas confondus";
return 0;
}
26
04/12/2023
• les règles de priorité et d’associativité sont les mêmes que pour les opérateurs
standards
• Les opérateurs new, delete, [ ], ( ), -> ne peuvent pas être surdéfinis par des
fonctions externes, mais uniquement par des fonctions membres.
1.Effectuer la surcharge de l'opérateur d'indexation ([]), alias operator[], dont la signature est :
... { String s5("ello"); cout << s5 << endl; ... cout << s5 << endl; } cout << "fin de code 4\n"; // ...
Avez-vous bien pensé à vérifier les débordements ?
27
04/12/2023
Opérateur d’indexation [ ]
• Il n’est pas possible d’accéder directement depuis une fonction utilisatrice à un élément d’un
tableau déclaré privé dans une classe (ne sont pas accessibles directement). Sans définition
une fonction avec un nouveau nom.
• La solution c’est de surdéfinir l’opérateur d’indexation [ ].
• La fonction de surdéfinition doit recevoir en argument le rang de l’élément. Elle renvoie sa
valeur.
• Si l’on veut pouvoir faire figurer l’élément à gauche d’un signe=, il faut utiliser la transmission
par référence pour l’argument de retour.
• On ne peut pas ici avoir recours à une fonction externe avec déclaration d’amitié.
Exemple:
class Tableau{
int * a ;
int nmax ;
public :
…};
Exemple:
using namespace std;
class Vecteur {
private:
int n;
int *a;
public:
void affiche(){
cout<<" liste "<<endl;
for (int i = 0; i < n; i++) cout<<" "<<a[i];
}
Vecteur(int t, int val) {n=t; a=new int [n];
for (int i=0; i<n;i++) a[i] = val;
}
int& operator[](int i) { return a[i];}
};
int main() {
const int N = 4;
Vecteur u(N, 7);
Vecteur v(N, 5);
for (int i = 0; i < N; i++)
v[i] += u[i];
v.affiche();
return 0;
}
B.M Cours C++ 56
28
04/12/2023
Exercice :
29
04/12/2023
Allocation dynamique
Lorsque les membres données d’une classe sont des pointeurs, le constructeur est
utilisé pour l’allocation dynamique de mémoire sur ce pointeur.
Pour certaines applications, on n’est pas capable de définir la taille d’un tableau au
moment de la compilation (exemple : tableau de mesures). La taille effective est fonction
d’un contexte d’éxécution. En conséquence, une allocation dynamique s’impose.
Les éléments du tableau seront accessibles via un pointeur qui sera une donnée
membre privée. Le destructeur est utilisé pour libérer la place. Il est obligatoire et doit
être pris en charge par le programmeur.
Exemple:
class tableau {
float *tab; int n;
public: // constructeur qui initialise x et y.
tableau(int m);
void lecture();
void affiche();
};
tableau::tableau(int m){
tab=new float[m]; n=m;
}
void tableau::affiche(){
cout<<"les éléments du tableau sont :"<<endl;
for(int i=0;i<n;i++)
cout<<" "<<tab[i];
}
void tableau::lecture(){
cout<<"entrer les éléments du tableau :"<<endl;
for(int i=0;i<n;i++)
cin>>tab[i];
}
int main() {
tableau pt(4);
pt.lecture();
pt.affiche();
return 0; B.M Cours C++ 60
}
30
04/12/2023
Exercice2
Créer une classe Etudiant permettant de représenter un étudiant caractérisé par des attributs
privés qui sont : nom, prénom et un tableau de dynamique de notes.
La classe comporte un constructeur qui accepte en argument le nombre de notes et qui permet
de lire au clavier le nom, prénom et les notes ,
• le destructeur si nécessaire
• une méthode affiche() pour afficher les différents attributs
• Une méthode qui parmi deux étudiants, affiche celui ayant la moyenne la plus grande
• Ecrire par ailleurs, un petit programme (main) de test
31
04/12/2023
Exemple:
class Entier {
public:
static int i;
static int get_value(void);
static void affiche(int a);
};
int Entier::i=3;
int Entier::get_value(void) { return i; }
void Entier::affiche(int a){ cout<<"la valeur est "<<i<<endl;}
int main(void) { // Appelle la fonction statique get_value :
int rs=Entier::get_value();
Remarque:
Entier::affiche(rs);
Entier E1,E2; - Le lieu naturel de la définition des variables membre statiques est le
E1.i++; fichier .cpp qui contient la définition des fonctions membre, et non le
Entier::affiche(E1.i); fichier .h définissant la classe elle-même.
E2.i=-1; - La définition d’une méthode statique se fait sans mentionner le mot
Entier::affiche(E2.i); static
return 0; - l’initialisation des variables static se font sans le mot static,
} nomdelaclasse::variablestatic=3333;
32
04/12/2023
Exercice:
Réaliser une classe nommée entier dont les membres données sont :
L’entier
Le compteur d’objets construits (variable statique entière)
Les fonctions membres sont :
Le constructeur, le destructeur, une fonction d’affichage et une fonction statique qui fournit le
nombre d’objets construits.
Héritage
La notion d’héritage est fondamentale en programmation orienté objet. Il s’agit de créer de
nouvelles classes, de nouveaux types, en se basant sur des classes déjà existantes.
L’héritage est en effet la définition d’une nouvelle classe, dite classe dérivée, à partir d’une classe
existante dite classe de base. Cette nouvelle classe hérite les membres non privés de la classe de
base (attributs et méthodes).
L’héritage permet :
• la réutilisation du code déjà écrit
• l’ajout de nouvelles fonctionnalités
• la modification d’un comportement existant (redéfinition)
Une classe peut hériter d’une classe qui peut elle-même hériter d’une autre etc...
Il existe donc une conversion implicite d’une classe fille vers un type de la classe parente.
33
04/12/2023
Héritage Simple
Tout se qui se trouve dans une classe A, et qui n’est pas privée se trouve également dans ses
classes dérivées.
Exemple :
Un étudiant est une personne, et a donc un nom (et un prénom, ...). De plus, il a un numéro
CNE.
Exemple 1:
à partir de la classe point que nous avons déjà utilisée (classe de base), nous voulons créer une autre classe
(classe dérivée) en ajoutant un symbole identifiant le point, qui sera une suite de un ou plusieurs
caractères. Nous appelons la classe dérivée Cercle.
Remarque: La classe dérivée Cercle a accès à tous les membres de la classe point qui ne sont pas privées.
34
04/12/2023
Exemple 2:
à partir de la classe point que nous avons déjà utilisée (classe de base), Créer une classe cercle (classe dérivée) en ajoutant
un rayon.
using namespace std;
class points{
private: float x,y;
public: points(float a=0, float b=0){ x=a; y=b; }
void afficher(){ cout<<"le point ("<<x<<","<<y<<") "; }
};
class cercle: public points{
private: float ry;
public: cercle(float r=0,float x=0,float y=0) : points(x,y){ ry=r; }
void afficher(){
cout<<"le cercle de centre ";
points::afficher();
cout<<" et de rayon "<<ry<<endl;
}
};
int main(){
cercle c(3,2,1);
c.afficher();
} B.M Cours C++ 69
Notion de redéfinition
• Une redéfinition (overriding) permet de fournir une nouvelle définition d’une méthode
d’une classe ascendante pour la remplacer. Elle doit avoir une signature rigoureusement
identique à la méthode parente.
Un objet garde toujours la capacité de pouvoir redéfinir une méthode afin de la réécrire ou de la
compléter.
35
04/12/2023
• Comme une instance de cercles(classe dérivée) est avant tout une instance de points(classe de
base), dans le constructeur de cercles, on crée explicitement l’instance points dans
l’initialisation.
• Le constructeur de points(classe de base) est appelé avant le constructeur de cercles(classe
dérivée).
• les destructeurs sont appelés dans l’ordre inverse (de la clase dérivée à la classe de base)
Une fonction de la classe dérivée peut appeler n’importe quelle fonction (protected, public) de la classe de
base, en utilisant l’opérateur de résolution de portée ::
Nom_classe::nom_fonction(arguments)
Exemple: On prévoit dans la classe dérivée Cercles une fonction d’affichage appelée afficher() qui appelle la
fonction afficher() de la classe points pour afficher le centre et le rayon d’un cercle.
- Cas fonction porte le même nom que la classe de base:
void Cercles::afficher(){
cout<<"le cercle de centre ";
points::afficher();
cout<<" et de rayon "<<ry<<endl;
}
36
04/12/2023
Types d’héritage:
37
04/12/2023
Conversion automatique:
Si B hérite de A, alors toutes les instances de B sont aussi des instances de A, et il est donc possible de faire :
A a; B b;
a=b; // affectation acceptée
b=a; // affectation n’est pas acceptée, erreur
Exemple:
class Etudiants : public Personnes{
}
Personnes pers;
Etudiants etud;
pers=etud;
Réaliser une classe vecteur d’entiers dont les membres données sont le nombre d’éléments du
vecteur et un pointeur d’entiers.
avec toujours pour fonctions membres
- le constructeur qui reçoit la taille du vecteur qui permet de créer et remplir ce vecteur au
clavier
-Le destructeur (Afficher les adresses des différents objets crées et détruits)
- Une fonction de surdéfinition de [ ]
- Une fonction d’affichage
- La fonction de surdéfinition de l’afféctation
Ecrire un programme principal de test.
38
04/12/2023
Une classe dérivée peut avoir une fonction membre de même nom que la classe de base et redéfinir
celle-ci.
Toujours la fonction de la classe dérivée fera appel à la fonction de la classe de base en utilisant
l’opérateur de résolution de portée :: et pourra compléter l’action de celle-ci.
Ainsi, au lieu de créer une fonction affichec membre de la classe dérivée, il est préférable de redéfinir
avec le même nom la fonction affiche de la classe point.
39
04/12/2023
On souhaite que, lorsqu’une fonction d’une classe est appelée, la fonction s’applique à l’objet effectif, et non pas à
l’objet déterminé à la compilation. C’est ce que l’on appelle le polymorphisme.
Pour cela, il suffit de déclarer la fonction virtuelle dans la classe de base.
Par exemple, si l’on a :
class A class B: public A
{ ... { ...
public : public :
virtual void fct(…); void fct(…);
… …
}; };
A *pta;
B *ptb;
Ainsi, si pta=ptb;
pta->fct(…) appelle la fonction fct de la classe B.
• Remarque :
Pour que la liaison dynamique puisse se faire, il faut que la fonction soit appelée par un pointeur et non directement par
l’objet lui-même.
40
04/12/2023
Reprenons le même exemple en donnant l’attribut virtual à la fonction affiche() dans la classe
de base point.
// fonction utilisatrice
main ( ) {
pointcar a(1.5, 2, "A") ;
point x(-0.5,3.) ;
pointcar *b=&a ;
point * y=&x ;
y=b; b->affiche ( ); y->affiche ( );
}
Le résultat est le suivant :
Coordonnées : 1.5 2
Identificateur : A
Coordonnées : 1.5 2
Identificateur : A
Ici, le type effectif de b est point avant affectation, son type devient pointcar
suite à l’affectation y=b.
41
04/12/2023
HERITAGE MULTIPLE
Principe : une classe peut dériver de plusieurs classes.
Dérivation à partir de plusieurs classes
• Déclaration d’une classe dérivée de plusieurs classes
Soient deux classes A et B déclarées par :
class A { class B {
... }; ...};
Pour définir une nouvelle classe C qui dérive de A et B, on la déclare par :
class C : public A, public B{
... } ;
Soit les classes Salaire et Identificateur suivantes :
Nous pouvons créer une classe employé caractérisé par le nom de l’employé et son salaire en la dérivant à partir des
deux classes précédentes.
Syntaxe de déclaration :
class Employé : public Salaire, public Identificateur{
... } ;
B.M Cours C++ 83
Exercice
Donnez programme complet de définition et d’utilisation de la classe Employé à partir des classes Salaire et
Identificateur (avec les constructeurs et les fonctions d’affichage)
42
04/12/2023
Si des membres donnés des classes de base accessibles, portent le même nom dans plusieurs classe de base, cela ne pose pas
de problème. Il suffit d’utiliser l’opérateur de résolution de portée : : pour spécifier la classe dans laquelle il faut prendre
l’objet. Ainsi :
A : : x désigne un objet x membre de la classe A
B : : x désigne un objet x membre de la classe B
Exemple:
Donnons aux membres de la classe Salaire et de la classe Identificateur le statut protected et introduisez dans la classe
Employé une fonction coïncide qui renvoie un bool valant true si 2 employés possèdent le même nom et même salaire, et
false sinon. Nous supposons que le nom du membre donné de la classe Salaire est x , et le nom du membre donnée de
Identificateur est aussi x. Ecrire le programme complet.
Classes Virtuelles
43
04/12/2023
Déclaration de classes:
class B : public A class C : public A
{ ... }; {...};
Lorsqu’on crée un objet de type D, Les constructeurs sont appelés dans l'ordre
suivant:
Le C++ permet de n'incorporer qu'une seule fois les données. Il suffit pour cela de déclarer dans les classes B et C
que la classe A est virtuelle. On spécifie tout simplement l’attribut virtual dans les déclarations des classes B et
C. On écrira:
L'attribut virtual n'a pas d'effet sur les classes B et C, mais uniquement sur les descendants éventuels de B et C.
44
04/12/2023
Exercice:
• Ecrire une classe étudiant caractérisée des attributs nom, prenom code et d’une moyenne, un constructeur,
• une classe Enseignant caractérisée par le nom, prenom, le nombre d’heure enseignées et un taux horaire. Et comporte
un constructeur
• Certains étudiants peuvent effectuer des enseignements
(vacations). En utilisant l'heritage multiple, Ecrire, une classe
etudiantVacataire heritant de Enseignant et etudiant et comporte un
constructeur.
• Ecrire un programme principal de test
45