La Programmation à Objets
Najib TOUNSI
Notes de cours: 2e année Informatique EMI
LES FONDEMENTS DE LA POO
LES CONCEPTS DE LA POO
LES LANGAGES A OBJETS
n
✔ LANGAGE C++
C + TAD. ( + qques améliorations)
(Bjarn STROUSTRUP)
✔ LANGAGE EIFFEL
Nouveau langage ( Fiabilité des programmes ).
(Bertrand MEYER)
✔ JAVA
Nouveau langage ( C++like, API très riches,
Fonctionnalités Sytèmes, Réseaux, etc ... )
✔ La Classe d'Objets
Classe, Fonctions Membres/Amies, Caractéristiques Publiques/Privées.
✔ Les Constructeurs et Destructeurs
Instanciations / Initialisations d'Objets. Libérations d'Objets.
✔ Classes Dérivées
Héritage Simple/Multiple. Accès protégé.
✔ Généricité
Classe et Fonction Génériques (template)
✔ Collections et Itérateurs
Parcours et Traitements des Collections
✔ Divers
La Classe d'Objets (exemple)
_
class Article{
int numero; // numéro article char* nom; // nom article
float prixHT; // son prix hors taxe int qte; // quanité en stock
public:float prixTTC ()
{ return prixHT*1.19;}
// opération qui calcule le prixTTC d'un article void ajouter (int q)
{ qte = qte + q;}
// opération qui augmente la quantité en stock void retirer (int q)
{ qte = qte - q;}
// opération qui diminue la quantité en stock
La Classe d'Objets (suite)
☞
✘
class introduit une définition de classe
✔ Enumération des caractéristiques (cf. Struct)
✔ Champs et méthodes sont dits
field /function members
✘
Membres publiques ou Privés
✔ public : Caractéristique connue en dehors de la classe (exportable)
✔ private : Non exportable. Usage interne de la classe. (Information Hiding).
✔ défaut private
La Classe d'Objets (suite)
✘
Fonctions membres définies en ligne (in line)
✔ Donnée de toute la définition d'une fonction membre.
✔ Appel = Expansion de la fonction au lieu de branchement (Si possible).
✘
Opérateur de résolution de Portée (Scope résolution Operator) ::
✔ Définition fonction membre en cas de donnée de prototype seul.
class Article{
...
void ajouter (int);
};
void Article::ajouter (int q){
qte = qte + q;
}
✘
Commentaires C++.
✔
/* comme c'est le cas en C */
La Classe d'Objets (Forme Générale)
fields vs functions public vs private members in line function
class nom {
field members function members
}
class nom {
private members public:
public members private:
private members
}
class nom {
void f(){…}
}
________________
class nom {
void f();
}
void nom::f(){…}
La Classe d'Objets (Exemple d'utilisation)
✔
Déclaration Article a;
✔
Appel de méthode: a.ajouter (5);
x = a.prixTTC();
u a.prixHT = 3.50; // incorrect
La Classe d'Objets (membres statiques)
☞ Champ déclaré static
class C{
public: static int s;
int a;
}
✔
Existe en un exemplaire. Partagé par toutes les instances.
✔
Référence: instance.membre classe::membre C x,y;
x.s, y.s, C::s → même objet.
✔
Intérêt: Ressource unique à gérer. (fichier, file d'attente, liste…)
'
La Classe d'Objets (fonction amie, friend member)
Fonction C normale qui jouit du privilège d'avoir accès aux membres privés d'une classe.
✔
On la déclare friend au sein de la classe. z
class Article { ...
friend void print(article);
}
void print(Article a) {
cout << a.numéro << a.nom << a.prixHT
<< a.qte;
}
✔
Evite de faire systématiquement appel à des fonctions d'accès pour des routines d'usage générale.
✔
Usage: print (x); print (y);
☞ Comparer à x.prixttc(); …i.e. appel de méthode.
La Classe d'Objets (Mais où est donc passée la pile?)
class pile{
char t[MAX];// Tableau des éléments de // la pile
int top; // Indice sommet de la pile.
public:
void vide();
// Initialise la pile à vide void empiler(char);
// Met un char en sommet de pile void depiler();
// Décapite la pile char sommet();
// Consultation du sommet de pile int estVide();
// Teste si pile vide (1 oui, 0 non)
};
void pile::vide(){
top = -1;
}
void pile::empiler(char c){
if (top < MAX) t[++top] = c;
else cout << "Pile pleine";
}
int pile::sommet(){
return t[top];
}
…
La Classe d'Objets
Exercices
Ecrire en C++ un programme qui utilise une pile.
Décrire une classe d'objets Date. Prévoir une fonction durée.
Décrire deux façons différentes de la faire.
(réponse: amie ou normale)
Décrire une classe d'objets nombre complexe.
Constructeurs et Destructeurs
Un constructeur, est une méthode (fonction membre) qui crée et/ou initialise une instance.
✘ Une Classe a intérêt à avoir, au moins, un constructeur.
✔
Initialiser des champs
✔
Allouer la place aux pointeurs
…
✘ Opération reconnue et systématiquement appelée par le compilateur.
Constructeurs et Destructeurs
(Rappel langages conventionnels )
Création / Destruction d'objets
✔ Entrée d'un bloc (ou Début de pgme)
✔ malloc() ou new
✔ Sortie du bloc
(ou Fin de pgme)
✔ free ou delete
Constructeurs et Destructeurs
(Rappel langages conventionnels )
int g; // objet g créé au lancement du programme (main donc) // et détruit à la fin de main. Zone statique.
void f(int p) { int l; } main() {
int x; // x entier est créé.
int *pt; // pointeur (valeur adresse) est créé
f(x); // p et a créés zone pile (dynamique) avec copie de x dans p // retour de f(), p et l détruits
pt = new int; // un objet entier est créé en zone tas (dynamique) delete pt; // cet objet est détruit (sa place libérée)
}
// x, pt et g détruits.
Constructeurs et Destructeurs
{ Type p;
… }
{ Type' q;
… }
✔
Appel systématique d'un constructeur dès la déclaration.
Constructeurs et Destructeurs
Un destructeur, est une fonction membre qui restitue au système l'espace occupée par une instance.
p = new type;
delete p;
p = new type';
delete p;
✔ Destructeur utile pour libérer (free) de la mémoire supplémentaire allouée.
(en cas d'absence de ramasse-miettes)
Constructeurs et Destructeurs (Définition)
class X {
X(){…}; // Constructeur défaut
X(TypeParam){…}; // 2e Constructeur
X~(){…}; // Destructeur
}
✔ Il peut (et doit) y avoir plusieurs constructeurs. (cf. surcharge) .
✔ Leur usage dépend du contexte.
✔ Un seul destructeur est possible (ou aucun).
✔ Définis en ligne de préférence.
FGHHJ
Constructeurs et Destructeurs (Usage)
{
X x; // X () appelé (constr défaut).
X y(par); // X (TypeParam) appelé
} // Destructeur appelé ici. 2 fois.
Constructeur défaut est assez utile. Forme abrégée et habituelle d'une déclaration:
X a,b,c;
En réalite:
X x
est une forme abrégée de
X x = X();X y(par)
est une forme abrégée de
X y = X(par);i.e. Déclaration + Initilalisation
class article{
...
article(int, char*, float, int);
// Construit un article de numéro, // nom, prixHT et quantité données ...
};
Variable simple Varaible Pointeur
Article a = article(10, "pot", 10.00, 234);
Article a(10, "pot", 10.00, 234);
Article b = a;
Article c; // incorrecte,
// paramètres manquants.
article* pa =
new article(10, "pot", 10.00, 234);
ou bien
article* pa; // Correcte bien sûr !
❀ ❀
article::article(int n, char* m, float p, int q){
numero = n;
nom = new char[strlen(m)+1];
strcpy (nom, m);
prixHT = p;
qte = q;
};
❶ ❶
article::article~(){
delete nom;
};
Il y a copie et copie
Simple Affectation Y = X
Copie Superficielle shallow copy
Copie en Profondeur deep copy
Certains langages possèdent notations pour toutes ces affectations.
(operator=)
Article *a, *b;
a = b;
Article a, b;
a = b;
Article a, b;
a = b; // nouvelle aff=
Affectation Copie superficielle Copie Profondeur
Surcharge de = Nouvelle fonction membre: article* operator=(artcilce&){…};
article* article::operator=(article& p){
if(this == &p) return this; // c'était a=a;
delete nom; // !!
numero = p.numero;
nom = new char[strlen(p.nom) + 1];
strcpy (nom, p.nom);
prixHT = p.prixHT; qte = p.qte;
Exemple de jeu complet de constructeurs
r t
class X { ...
X() // Défaut // si souhaitable
X(objets_de_base);// A partir d'objets de base.
X(X&); // A partir d'instance existante // Paramètres de fonction.
X& operator=(X&); // Copie en profondeur.
~X();
};
X a;
f(a);
X a(…);
a = b;
Forme:
class D : public B { //caractéristique de D };D classe dérivée hérite de B classe de base
(avec transmission des droits publiques) Exemple:
typedef enum {S,M,L,XL} SIZE;
class vetement: public article{
SIZE taille;
char coloris[10];
// ...
};
class audioVisuel: public Article { int dureeGarantie;
// ...
};
class TV: public audioVisuel { int voltage;
// ...
};
Un seul niveau Deux niveaux
Constructeurs:
class vetement : public Article { // ...
public:
vetement(int , char*, float, int, SIZE, char*);
// les caractéristiques de base d'un article plus // celles d'un vetement
};
vet::vet(int n, char* m,float p,int q, SIZE s, char*
c)
: Article (n,m,p,q) // appel constr. parent { taille=s;
strcpy(coloris,c);
}
✔ Appel constructeurs en ordre ascendant.
Appels Constructeurs:
On initialise:
• D'abord la partie article
• Ensuite la partie vêtement vet v (12, "chemise", 10.00, 200, XL, "jaune");
➂ article: num
♦12, nom
♦"chemise", prixHT
♦10,00, num
♦200
➂ vet: taille
♦XL, coloris
♦"jaune"
✂ 1er niveau:
Transmission des droits d'accès des membres non privés hérités.
class D : public B {…};
membre publique de B, membre publique dans sous classe de D
✆ 2e niveau: Membres privés pour tous sauf pour les descendants . class X { protected : membres …};
(membres «privé» chez classes clientes, «publique» chez sous classes.
Exemple Synthétique
class X { private: int A; //ou protected ou public // ...};
ISA
class U{ // cliente de X Y et Z
h(){
X x; Z z; Y y;
x.A=1; y.A=1; z.A=1;
} };
USES
class Y: X { // ou Y: public X public:
f(){
X x; Y y;
x.A=1; y.A=1;
} };
ISA
class Z:Y { public:
g(){
X x; Z z; Y y;
x.A=1; y.A=1; z.A=1;
} };
template
➁ ➁ Fonction générique :
template <class Type> g(…) {…}template <class T> // fonction g de param T void g( T x){
… }
main(){
int x; float y; Article z;
(x); g(y); g(z);
}
Application: Une seule fonction tri, tableaux différents types
template
➁ ➁ Classe générique :
template <class Type> class G {…}template <class T>
class Pile { T P[10];
int s;
public:
Pile(){ s = -1;}
void empiler(T& e){ P[++s] = e;}
void depiler(){ s--; }
T sommet (){ return P[s]; } };
main(){
Pile <int> pi;
Pile <float> pf;
int n;
pi.empiler(2);
pf.empiler((float)2.2)
;
n = pi.sommet();
pi.depiler();
pf.depiler();
… }
Application: Une seule déscription, Plusieurs classes
✺
Itérateur: Mécanisme perméttant de parcourir une collection pour en traiter un à un les éléments
initialisation, progression automatique, test d'arrêt exemples :
Boucle for des langages de
programmation Notion de CURSOR dans ESQL/C
for (i=0; i<M; i++)
cout << t[i];
✽ declare c CURSOR for select * from employe
…
OPEN c; FETCH c into e
while (SQLCODE ==0){
traiter un employé e
Itérateur Abstrait: Itérateur permettant de faire abstraction de la stratégie d'accès aux éléments à traiter (début, accès au suivant, arrêt) .
PourChaque Elément de Collection
Traitement
PourChaque Elément de Collection TelQue Condition
Traitement
☞ Aucune hypothèse sur l'ordre ou la méthode de recherche des éléments traités
Classe Collection
//
// Collection generique //
template <class T> class Collection{
T* t[10];
short size;
public:
Collection(){
size=0;
for (int i=0; i<size; i++) t[i] = NULL;
}
void insert(T& e){
t[size++] = new T(e);
}
void suppr (T& e){
for (int i=0;i<size;i++) if(cmp(*t[i],e)==0){
*t[i] = *t[--size];
delete (t[size]);
} }
~Collection(){
for (int i=0; i<size; i++) delete (t[i]);
}
// ...
friend class iterator;
};
Itérateur sur une collections de String
typedef Collection<String> Strings;
class iterator{
Strings *s; // référence au set a parcourir int cursor; // élément courant
public:
iterator (Strings &x){
// on itere sur x s = &x;
cursor = 0;
}
String* operator() () // suivant {
return (cursor < s->size ?
&(s->t[cursor++]) : NULL );
} };
main(){
Strings setStr;
iterator get(setStr); //init iterateur /…
String *x;
while ( (x=get()) != NULL) x->print();
}
Itérateur sur une collections de article
#include "article.h"
#include "collection.h"
typedef Collection<Article> Articles;
class iterator{
Articles *s;
int cursor;
public:
iterator (Articles &x){
s = &x;
cursor = 0;
}
Article* operator() () // suivant {
return (cursor < s->size ? s->t[cursor++] : NULL );
} };
Simple Itération Double Itération
main(){
Articles articles;
Article a(10, "titi", 25,10);
Article b(12, "toto", 25,10);
Article c(14, "tutu", 24,11);
articles.insert(a); articles.insert(b);
articles.insert(c);
iterator get(articles);
Article *x =new Article(0,"\0",0,0);
while ( (x=get())!= NULL) x->print();
}
main(){
// ... mêmes initialisations iterator get1(articles);
iterator get2(articles);
Article *x =new Article(0,"\0",0,0);
Article *y =new Article(0,"\0",0,0);
while ( (x=get1())!= NULL){
x->print();
get2=iterator(articles);
while( (y=get2()) !=NULL){
printf(" 2 ");
y->print();
} }
}