61
Structures de données IFT-10541 Abder Alikacem Abder Alikacem Programmation orienté objet en C++ Module 2 Département d’informatique et de génie logiciel Édition Septembre 2009

Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Embed Size (px)

Citation preview

Page 1: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Structures de donnéesIFT-10541

Abder AlikacemAbder Alikacem

Programmation orienté objet en C++Module 2

Département d’informatique et de génie logiciel

Édition Septembre 2009

Page 2: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Plan

• Introduction au mondes des objets: les concepts• Le concept d'Objet• Les principes de l’Approche Orientée Objet• Les relations entre Objets• Quelques définitions

• Principe de l’encapsulation• Classes et objets• Les modèles (templates)

• Programmation générique : introduction, exemples• Déclaration des modèles• Fonctions et méthodes génériques• Instanciation• Spécialisation• Compilation séparée

• Traitement des exceptions

Page 3: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Le concept d’objet (1/3)

• Exemple : une personne, une voiture, une procédure, une loi, ...• Objet :

• abstraction du monde réel• entité possédant

• un état (information)• offrant des services / opérations pour examiner / modifier son état (comportement)

• Modèle Orienté-Objet (OO) d’une application : définition d’un ensemble d’objets coopérants - communicants - et concurrents - vivants indépendamment les uns des autres

Page 4: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Le concept d’objet (2/3)

• Objet = identité + état + comportement• Exemple : la voiture 1875 WC 31

• état : immatriculation, kilométrage, vitesse instantanée, état interne…

• services / opérations : • accesseurs : kilométrage?, immatriculation? ...• modificateurs : démarrer, s’arrêter, se déplacer, tomber en panne, être réparée ...

• Essentiel : un objet n'est manipulable qu'à travers son interface i.e. ses opérations publiques

Page 5: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Le concept d'objet (3/3)

• Tout objet a une durée de vie finie : il naît, vit et meurt !• Tout objet est en relation avec d'autres objets :

• relations statiques : (relativement) stables dans le temps• relations dynamiques : brèves, limitées à la communication

• Tout objet peut changer de forme - sous certaines conditions - au cours de son existence : principe de polymorphisme

Page 6: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Principes sur lesquels reposent les Objets

• Encapsulation : regroupement des informations d'état et de comportement sous un nom unique

• Masquage d'information : on ne connaît pas la structure de l'information

• Interface : seuls les services publics (offerts à l'extérieur) sont utilisables

• Envoi de messages : les objets communiquent par messages• Durée de vie limitée : dépendante du contexte

Page 7: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Les relations entre Objets

• Relations statiques :• composition / agrégation : traduit l'assemblage• généralisation / spécialisation : permet la réutilisation• association n-aire : relation classique

• Relations dynamiques :• communication : échange de données• signal : échange de stimuli

Page 8: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Généralisation / spécialisation

• Généralisation : a posteriori pour favoriser la réutilisation future• Spécialisation : c'est de la réutilisation

• en extension : ajout de nouvelles propriétés• en compréhension : modification de propriétés

Conséquences :• Polymorphisme : possibilité pour une instance de changer de classe

tout en restant dans la même hiérarchie• Héritage simple / multiple

Page 9: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Représentation d'objet

kilométrage : ...vitesse : ...immatriculation : ...

kilométrage?

démarrer

tomber en panne...

La voiture de Jean

Son nom

Un objet

Son état

Opération privée

Opération publique

Page 10: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Quelques définitions

• Classe = regroupement d'objets ayant des propriétés (état et/ou comportement et/ou relations) communes

• Classe = moule qui décrit la structure interne d'un ensemble d'objets• Classe = abstraction qui n'a de sens qu'à la compilation

• Objet = un instance d'une classe• Objet = instance qui n'a d'existence qu'à l'exécution

Page 11: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Propriétés des objets

• Unicité : • un objet n'est instance que d'une classe et d'une seule• une instance a une identité (interne) unique

• Durée de vie : • une instance doit être déclarée, puis définie en fonction du

contexte.• un objet vit sa vie puis meurt. • la durée de vie peut être très courte, très grande !

• Polymorphisme : un objet peut changer de forme au cours de sa vie !

• Concurrence : les objets évoluent indépendamment les uns des autres

Page 12: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Conception Orientée Objet

Identification des classes à réutiliser ou à concevoir :utilisation d’une méthode OO pour la conception et la définitiondes hiérarchies de classes à utiliser ou à développer

Construction de l’Application OO :transformation de la conception de l’application en un ensembled’objets concurrents et coopérants

Deux étapes fondamentalement différentes :

Page 13: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Intérêt des Objets

• Maîtrise de la complexité : • l'encapsulation permet de se concentrer sur un(e) objet(classe) et

un(e) seul(e)• il est possible de tester de façon quasi exhaustive un objet

• Evolution facilitée : rajouter de nouveaux objets est simplifié. On les raccroche aux modèles déjà construits par spécialisation

• Réutilisation : vraiment possible à cause des classifications induites par la relation de spécialisation / généralisation !

• ...

Page 14: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Inconvénients de l'approche OO

• Tout n'est pas objet : se méfier des chapelles et des gourous !• Tester un ensemble un système OO est difficile !• Penser objet oblige à changer de mentalité !

Page 15: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Encapsulation, polymorphisme et héritage

Encapsulation • Le rassemblement des données et du code les utilisant dans une entité unique (objet). • La séparation nette entre la partie publique d'un objet (ou interface) seule connue de l'utilisateur de la partie privée ou implémentation qui reste masquée.

Polymorphisme • Une méthode peut adopter plusieurs formes différentes.

Héritage • Possibilité de définir des familles de classes traduisant le principe de généralisation / spécialisation. « La classe dérivée est une version spécialisée de sa classe de base »

Page 16: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Encapsulation et abstraction

L'encapsulation

•Consiste à masquer l'accès à certains attributs et méthodes d'une classe. Pourquoi masquer?

•Cacher les détails d'implémentation des objets à l'utilisateur permet de modifier, par exemple la structure de données interne d'une classe (remplacer un tableau par une liste chaînée) sans pour autant entraîner de modifications dans le code de l’utilisateur, l’interface n’étant pas atteinte.

Abstraction de données

•La structure d'un objet n'est pas visible de l'extérieur, son interface est constituée de messages invocables par un utilisateur. La réception d'un message déclenche l'exécution de la méthode correspondant à ce message.

Abstraction procédurale

•Du point de vue de l'extérieur (c’est-à-dire en fait du client de l’objet), l'invocation d'un message est une opération atomique. L'utilisateur n'a aucun élément d'information sur la mécanique interne mise en œuvre. Par exemple, il ne sait pas si le traitement requis a demandé l’intervention de plusieurs méthodes ou même la création d’objets temporaires etc.

Page 17: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Droits d’accès

En C++, on choisit les paramètres d’accès aux membres d’une encapsulation à l'aide des mots clés :

private : les membres privés ne sont accessibles que par les fonctions membres de la classe.

protected : les membres protégés sont comme les membres privés. Mais ils sont aussi accessibles par les fonctions membres des classes dérivées.

public : les membres publics sont accessibles par tous. La partie publique est appelée interface.

Les mots réservés private , protected et public peuvent figurer plusieurs fois dans la déclaration de la classe. Le droit d'accès ne change pas tant qu'un nouveau droit n'est pas spécifié.

Page 18: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Les différents type d’encapsulation

Il existe différents types d’encapsulation :

• struct Classe1 { /* ... */ };

tous les membres sont par défaut d'accès public par défaut.

• union Classe2 { /* ... */ };

tous les membres sont d'accès public par défaut.

• class Classe3 { /* ... */ };

tous les membres sont d'accès private par défaut.

C'est cette dernière forme qui est utilisée en C++ pour définir des classes.

Page 19: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Principe de la conception orienté objet

• Approche traditionnelle• Organiser autour du traitement

Algorithmes + Structures de données = Programme

Fonction 1

Structures de données

Fonction 2

Fonction 3

Fonction n

Page 20: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Principe de la conception orienté objet

Organiser autour des données à manipuler

DonnéesFonctions de

manipulations etde traitements

Obj

et

Page 21: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Objet en C++

typedef struct { int jour; int mois; int année;} Date;

void initData(Data d,int j,int m,int a){ d.jour=j; d.mois=m; d.année=a;}

int main(){ Date d; initData(d,2,2,2004); return 0;}

Class Date {public : void initData(int j,int m,int a);protected: int _jour; int _mois; int _année;};

Date::initData(int j,int m,int a){ _jour=j; _mois=m; _année=a;}

int main(){ Date d; d.initData(2,2,2004); return 0;}

Programme C Programme C++

Page 22: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Interface d’une classe (fichier .h)

• Section public

• Attributs public• Méthodes public

• Constructeur• Destructeur• Fonction d’accès

• Section protected• Attributs et méthodes accessibles

par les membres de la classe et des classes dérivées

• Section private• Attributs et méthodes accessibles

uniquement par les membres de la classe

class Date {

public : int var1; Date(); ~Date();

void initialiser(int j,int m,int a); void afficher(); int getJour(); int getMois(); int getAnnee(); setJour( int j); setMois(int m); setAnnee(int a);

protected: int _jour; int _mois; int _année; void _test();

private:};

Page 23: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Implantation d’une classe (fichier .cpp)

• Définition des méthodes de la class :

• Constructeur• Destructeur• Fonction d’accès

Date::Date(){ _jour=0; _mois_0; _annee=0;} Date::~Date(){}

void Data::afficher(){ cout << "la date : " << _jour ; cout << "/" << _mois ; cout << "/" << _annee << endl; } int Data::getJour() {return _jours;}int Data::getMois() {return _mois;};int Data::getAnnee(){return _annee;}

Data::setJour(int j) {_jour =j;}Data::setMois(int m) {_mois =m;}Data::setAnnee(int a){_annee=a;}

Page 24: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Réutilisabilité

On cherche à écrire des objets réutilisables.

On aimerait concevoir une classe qui modélise une pile de portée générale : une pile n’importe quels composants.

==> Concevoir une classe générique

pile<char> Pcar;

pile <personne> Ppersonne;

Page 25: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Facteur de qualité d’un logiciel

Réutilisabilité

Possibilité d ’obtenir toutes les occurrences d ’une classe s ’appliquant à différents types, en ne décrivant qu’une seule fois la classe.

Une classe décrit une famille d ’objets :• Cohérente• Lisible• Extensible• Réutilisable

Page 26: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

L’idée de base est de passer les types de données comme paramètres

pour décrire des traitements très généraux (« génériques »).

Il s’agit donc d’un niveau d’abstraction supplémentaire. De tels modèles de classes/fonctions s’appellent aussi classes/fonctions génériques ou patrons (chablons), ou encore « template ».

Vous en connaissez déjà sans le savoir. Par exemple la « classe » Vector de la STL n’est en fait pas une classe mais un modèle de classes : c’est

le même modèle que l’on stocke des char (vector<char>), des int

(vector<int>), ou tout autre objet.

Page 27: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

Prenons un exemple simple pour commencer : une fonction échangeant la

valeur de 2 variables.

Par exemple avec 2 entiers vous écririez une fonction comme :

// échange la valeur de ses argumentsvoid echange(int& i, int& j) {

int tmp(i);i = j;j = tmp;

}

Mais vous vous rendez bien compte que vous pourriez faire la mêmechose (le même algorithme) avec deux double, ou même deuxobjets quelconques, pour peu qu’ils aient un constructeur de copie(Obj tmp(i);) et un opérateur de copie (operator=).

Exemple simple pour commencer

Page 28: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

L’écriture générale serait alors quelque chose comme :// échange la valeur de ses argumentsvoid echange(Type& i, Type& j) {

Type tmp(i);i = j;j = tmp;

}

où Type est une représentation générique du type des objets àéchanger. La façon exacte de le faire en C++ est la suivante :

// échange la valeur de ses argumentstemplate<typename Type>void echange(Type& i, Type& j) {

Type tmp(i);i = j;j = tmp;

}

Exemple suite…

Page 29: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

On pourra alors utiliser la fonction echange avec tout type/classe pourlequel le constructeur de copie et l’opérateur d’affectation (=) sont

définis.

Par exemple :int a(2), b(4);echange(a,b);double da(2.3), db(4.5);echange(da,db);vector<double> va, vb;...echange(va,vb);string sa("ca marche"), sb("coucou");echange(sa, sb);

Exemple suite…et fin

Page 30: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

Second exemple d’une fonction générique

template <class X >X min (const X& A,const X& B){

if (A<B) return(A);return (B);

}

intmain (){int i,j,m;cin >> i,j;int m=min <int>(i,j);...}

L ’opérateur < doit être surchargé dans les classes quiutiliseront le modèle min

Le compilateurinstancie une fonctionint min (const int&, const int&)

Page 31: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

Généralisation aux classes

Une classe générique est une classe avec un template. Même principe queles fonctions génériques.

template <typename T>class Nb{public :

T a, b;T add (){ return a+b};

};

Nb<int> N;N.a = 1;N.b = 2;cout << N.Add() << endl;

Page 32: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

On pourrait par exemple vouloir créer une classe qui réalise une paire d’objets quelconques :

template<typename T1, typename T2>class Paire {public:

Paire(const T1& un, const T2& deux): premier(un), second(deux) {}

virtual ˜Paire(){}T1 get1() const { return premier; }T2 get2() const { return second; }void set1(const T1& val) { premier = val; }void set2(const T2& val) { second = val; }

protected:T1 premier;T2 second;

};

Généralisation aux classes

Page 33: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

et par exemple créer la classe « paire string–double » :

Paire<string,double>

ou encore la classe « paire char–unsigned int » :

Paire<char,unsigned int>

Note : un tel modèle de classe existe dans la STL : pair.

Les modèles de classes sont donc un moyen condensé d’écrireplein de classes potentielles à la fois.

Généralisation aux classes

Page 34: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

Pour déclarer un modèle de classe ou de fonction, il suffit de faire précéder sa déclaration du mot clé template suivit de ses arguments (qui sont donc des noms génériques de type) suivant la syntaxe :

template<typename nom1, typename nom2, ...>

Exemple template<typename T1, typename T2>class Paire {...

Déclaration d’un modèle

Le paramètre générique effectif d ’une classe peut être un identificateur de type prédéfini ou un identificateur de classe.

Page 35: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

Pour déclarer un modèle de classe ou de fonction, il suffit de faire précéder sa déclaration du mot clé template suivit de ses arguments (qui sont donc des noms génériques de type) suivant la syntaxe :

template<typename nom1, typename nom2, ...>Exemple

template<typename T1, typename T2>class Paire {...

Les types ainsi déclarés (paramètres du modèle) peuvent alors être utilisés dans la définition qui suit, exactement comme tout autre type.

Note : on peut aussi utiliser le mot class à la place de typename, par exemple :

template<class T1, class T2>class Paire {...

Déclaration d’un modèle

Page 36: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

Si les méthodes d’un modèle de classes sont définies en dehors de cette classe, elle devront alors aussi être définies comme modèle et être précédées du mot clé template, mais... ...il est de plus absolument nécessaire d’ajouter les paramètres du modèle (les types génériques) au nom de la classe [ pour bien spécifier que dans cette définition c’est la classe qui est en modèle et non la méthode. ]

Exemple template<typename T1, typename T2> class Paire {public:

Paire(const T1&, const T2&);...

};// définition du constructeurtemplate<typename T1, typename T2>Paire<T1,T2>::Paire(const T1& un, const T2& deux): premier(un), second(deux) { }

Définitions externes des méthodes de modèles de classes

Page 37: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

La définition des modèles ne génère en elle-même aucun code : c’est juste une description de plein de codes potentiels.

Le code n’est produit que lorsque tous les paramètres du modèle ont pris chacun un type spécifique. Lors de l’utilisation d’un modèle, il faut donc fournir des valeurs pour tous les paramètres (au moins ceux qui n’ont pas de valeur par

défaut). On appelle cette opération une instanciation du modèle.

L’instanciation peut être implicite lorsque le contexte permet au compilateur de décider de l’instance de modèle à choisir. Par exemple, dans le code :

double da(2.3), db(4.5);echange(da,db);

il est clair (par le contexte) qu’il s’agit de l’instance echange<double>du modèle template<typename T> void echange(T&,T&); qu’il faut

utiliser.

Instanciation des modèles

Page 38: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

Mais dans la plupart des cas, on explicite l’instanciation lors de la déclaration d’un objet. C’est ce qui vous faites lorsque vous déclarez par exemple

vector<double> tableau; Il suffit dans ce cas de spécifier le(s) type(s) désiré(s) après le nom du modèle de classe et entre <>.

L’instanciation explicite peut aussi être utile dans les cas où le contexten’est pas suffisamment clair pour choisir. Par exemple avec le modèle de

fonctiontemplate <typename Type>Type monmax(const Type& x, const Type& y) {

if (x < y) return y;else return x;

}

l’appel monmax(3.14, 7); est ambigu. Il faudra alors écrire monmax<double>(3.14, 7);

Instanciation des modèles

Page 39: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

Les modèles de fonctions peuvent très bien être surchargés comme les fonctions usuelles (puisque, encore une fois, ce sont juste une façon condensée d’écrire plein de fonctions à la fois). Par exemple :

template<typename Type>void affiche(const Type& t) {cout << "J’affiche " << t << endl;

}// surcharge pour les pointeurs : on préfère ici écrire// le contenu plutôt que l’adresse.template<typename Type> void affiche(Type* t) {

cout << "J’affiche " << *t << endl;}

Note : on aurait même pu faire mieux en écrivant :template<typename Type> void affiche(Type* t) {

affiche<Type>(*t);}

qui fait appel au premier modèle.

Modèles, surcharge et spécialisation

Page 40: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

Mais les modèles (y compris les modèles de classes) offrent un mécanisme supplémentaire : la spécialisation qui permet de définir une version particulière d’une classe ou d’une fonction pour un choix spécifique des paramètres du modèle. Par exemple, on pourrait spécialiser le second modèle ci-dessus dans

le cas des pointeurs sur des entiers :

template<> void affiche<int>(int* t) {cout << "J’affiche le contenu d’un entier: " << *t <<

endl;}

La spécialisation d’un modèle (lorsqu’elle est totale) se fait en :ajoutant template<> devant la définitionnommant explicitement la classe/fonction spécifiée

C’est le <int> après affiche dans l’exemple ci-dessus.

Modèles, surcharge et spécialisation

Page 41: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

template<typename T1, typename T2>class Paire {...};// spécialisation pour les paires <string,int>template<> class Paire<string,int> {public:

Paire(const string& un, int deux) : premier(un), second(deux) {}virtual ˜Paire() {}string get1() const { return premier; }int get2() const { return second; }void set1(const string& val) { premier = val; }void set2(int val) { second = val; }// une méthode de plusvoid add(int i) { second += il }

protected:string premier;int second;

};

Exemple de spécialisation de classe

Page 42: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

Note 1 : La spécialisation peut également s’appliquer uniquement à une méthode d’un modèle de classe sans que l’on soit obligé de spécialiser toute la classe.Utilisée de la sorte, la spécialisation peut s’avérer particulièrement utile.

Note 2 : La spécialisation n’est pas une surcharge car il n’y a pas génération de plusieurs fonctions de même nom (de plus que signifie une surcharge dans le cas d’une classe ?) mais bien une instance spécifique du modèle.

Note 3 : il existe aussi des spécialisations partielles (de classe ou de fonctions), mais cela nous emmènerait trop loin dans ce cours.

Spécialisation: remarques

Page 43: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Exemple 2

template <typename T, int taille_max = 200>// Le paramètre entier max_size a la valeur 200 par défaut.class pile {public: typedef T value_type;private:

T* laPile ;int sommet ;

public:pile() : sommet(0) { laPile = new T [taille_max] ; }~pile() { delete [] laPile ; }void empiler ( T c ) { laPile[ sommet++ ] = c ; }

// ...};

Programmation générique

Page 44: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Retour sur le typename

Le mot clef typename indique que le mot suivant doit être considéré comme un type. C’est le cas dans une déclaration template (où typename peut aussi être remplacé par class) et dans les cas où il y aurait ambiguïté ou si le type n’est pas encore instancié (paramètre d’un autre type, lui-même template).

template <class P, int taille_max = 200>class SacADos {// P::value_type n’est pas encore un type puisque T, n’a pas été instancié// Il faut donc l’indiquer au compilateur

typedef typename P::value_type T_values;...

};

Programmation générique

Page 45: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Fonctions et méthodes génériques

template permet aussi de déclarer des fonctions génériques, voire des fonctions membres génériques d’une classe générique. Cependant, ici, la spécification entre < et > n’est pas requise à l’appel car déduite des paramètres effectifs.

class pile {template <class T>void empiler(const T& a);

....};

template<class X>void explorer(const X& p) { ... };

int main() {pile p ; // instanciation d’une pile.char c = ’a’;// Ces appels sont valides.// Dans le premier cas ‘‘char’’ est déduit //du type de c.p.empiler(c);p.empiler<char>(c) ;explorer( p );explorer<pile>( p );return 0;

}

Programmation générique

Page 46: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Il est possible de créer des Tableaux d'entiers, de les manipuler comme les variables d'un type intégré et de les passer en paramètre sans avoir à fournir la taille comme paramètre supplémentaire.

Cependant notre solution ne fonctionne que pour des Tableaux d'entiers. Que se passe-t-il si on avait besoin de Tableaux de doubles ou de chaînes de caractères?

On voudrait pouvoir créer des Tableaux de types arbitraires sans avoir à définir une classe distincte pour chacun d'eux. Cela peut être fait à l'aide des modèles (templates).

Exemple 3

Programmation générique

Page 47: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

template<class elem>class Tableau{

private: int nbelements; int *T;

public:Tableau(int);Tableau(const Tableau&);~Tableau() {delete[] T;};int longueur() const {return nbelements;};elem& operator[](int) const;Tableau& operator=(const Tableau&);

};

Rappel: on peut écrire template <class elem> outemplate <typename elem>

Programmation générique

Page 48: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

template<class elem> Tableau<elem>::Tableau(int n){

T=new elem[n];nbelements=n;

}

template<class elem> Tableau<elem>::Tableau(const Tableau<elem> &tab){

T=new elem[tab.nbelements];(*this)=tab;

}

template<class elem> elem& Tableau<elem>::operator[](const int i) const{

return T[i];}

Programmation générique

Page 49: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

template<class elem>Tableau<elem>& Tableau<elem>::operator=(const Tableau<elem> &tab){

if (nbelements<tab.nbelements){

delete[] T;T=new elem[tab.nbelements];

}

nbelements=tab.nbelements;for (int i=0; i<nbelements; i++)T[i]=tab.T[i];

return *this;}

Programmation générique

Page 50: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

La définition de la classe est précédée de

templace<class elem>

qui indique que l'on défini un modèle et qu'un type elem apparaît en argument dans la déclaration de Tableau.

On peut alors déclarer un tableau d'entiers ou de double de la façon suivante:

Tableau<int> iTab(100);Tableau<double> dTab(20);

Programmation générique

Page 51: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Les modèles ne sont pas retreints aux classes comme on l’a déjà vu et commel'illustre les exemples suivants:

template<class C>void echanger(C &A, C &B){

C tmp=A;A=B;B=tmp;

}

template<class elem>void print(const Tableau<elem>& t){

for (int i=0; i<t.longueur(); i++)cout<<t[i]<<" ";cout<<endl;

}

Programmation générique

Page 52: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

La fonction echanger ne peut être utilisée que par une classe C possédant un constructeur de copie et un opérateur d'affectation.

La fonction print nécessite que l'opérateur << soit défini pour les objets de type elem. On peut appeler ces fonctions de la façon suivante:

int a=0, b=1;double x=1.0, y=2.3;Tableau<int> A(20), B(30);Tableau<char> C(100)//// initialisation de A, B et C//echanger(a,b);echanger(x,y);echanger(A,B);print(A);print(B);print(C);

Programmation générique

Page 53: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

Les modèle de classes doivent nécessairement être définis au moment de leur instanciation afin que le compilateur puisse générer le code correspondant. Ce qui implique, lors de compilation séparée, que les fichiers d’en-tête (.h) doivent contenir non seulement la déclaration, mais également la définition complète de ces modèles !!

On ne peut donc pas séparer la déclaration de la définition dans différents fichiers... Ce qui présente plusieurs inconvénients :

Les mêmes instances de modèles peuvent être compilées plusieurs fois,et se retrouvent en de multiples exemplaires dans les fichiersexécutables.On ne peut plus cacher leurs définitions (par exemple pour desraisons de confidentialité, protection contre la concurrence, etc...)

Modèles de classe et compilation séparée

Page 54: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

Notez également que les fichiers contenant des modèles ne sont pas des fichiers sources classiques, puisque sans instanciation, ils ne génèrent aucun code machine.

Pour résoudre ces problèmes, le langage C++ donne en principe la possibilité d’exporter les définitions des modèles dans des fichiers complémentaires à l’aide de la directive export.

Malheureusement celle-ci n’est pour l’instant (à ma connaissance) pas gérée par les compilateurs actuels :warning: keyword ‘export’ not implemented, and will be ignored

En l’état, il faut donc malheureusement joindre prototype et définitions des modèles dans les mêmes fichiers d’en-tête. Le seul « point noir » des templates est donc lié à la faiblesse des compilateurs actuels qui ne gèrent pas la directive export.

Modèles de classe et compilation séparée

Page 55: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Programmation générique

Déclarer un modèle de classe ou de fonction :

template<typename nom1, typename nom2, ...>

Définition externe des méthodes de modèles de classes :

template<typename nom1, typename nom2, ...>NomClasse<nom1, nom2, ...>::NomMethode(...

Instanciation : spécifier simplement les types voulus après le nom de la classe/fonction, entre <> (Exemple : vector<double>)

Spécialisation (totale) de modèle pour les types type1, type2... :template<> NomModele<type1,type2,...> ...suite de la declaration...

Compilation séparée : pour les templates, il faut tout mettre(déclarations et définitions) dans le fichier d’en-tête (.h).

Templates

Page 56: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Le traitement des exceptions

Le C++ contient un mécanisme très utile pour traiter les erreurs et autres exceptions.

Lorsqu'une erreur est détectée, il est possible de transmettre (throw)un objet à une partie du code qui reçoit (catch) l'objet et traite l'erreur.

Considérons, par exemple, la fonction operator[] de la classe Tableau. Il Serait prudent de vérifier la valeur de l'opérande afin de s'assurer qu'elle corresponde bien à un indice valide du tableau. Si tel n'est pas le cas, que doit faire la fonction? Elle ne dispose pas de l'information nécessaire pour traiter elle-même l'erreur et ne peut pas signaler l'erreur par une valeur de retour ou un paramètre.

Pour régler ce problème nous allons ajouter un membre publique et modifier la fonction operator[].

Page 57: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Le traitement des exceptions

template<class elem>class Tableau{

elem nbelements;elem *T;

public:struct erreur_indice{

int indice;erreur_indice(int i){indice=i;};

};

Tableau(int);Tableau(const Tableau&);~Tableau() {delete[] T;};int longueur() const {return nbelements;};elem& operator[](int) const;Tableau& operator=(const Tableau&);

};

Page 58: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Le traitement des exceptions

template<class elem>elem& Tableau<elem>::operator[](const int i) const{

if (i<0 || i>=nbelements) throw erreur_indice(i);

return T[i];}

Nous avons ajouté à Tableau la définition d'une structure afin de définirun type d'erreur correspondant aux dépassement des limites.

En C++ une structure est exactement comme une classe sauf que par défaut les membres sont publiques. Si operator[] détecte une erreur, il utilisera le constructeur de erreur_indice pour créer un objet qu'il transmettra via l'instruction throw. L'instruction throw se comporte un peu comme l'instruction return sauf qu'elle cherche dans la pile des appels de fonctions celle qui demande à recevoir l'objet.

Page 59: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Le traitement des exceptions

Exemple:template<class elem>void initialise(Tableau<elem>& t, const elem& E){

for (int i=0; i<=t.longueur(); i++)t[i]=E;

}

int main(){

Tableau<int> T(100);try{

initialise(T,0);}catch(Tableau<int>::erreur_indice e){

cerr<<"Erreur d'indice: <<e.indice<<endl;}

return 0;}

Page 60: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Le traitement des exceptions

La fonction main() utilise les mots clefs try et catch pour indiquer qu'elleappelle la fonction initialise et qu'elle désire traiter les erreurs de typeTableau<int>::erreur_indice.

Au dernier tour de boucle de initialise, l'indice i aura dépassé les limites du tableau et Tableau<int>::operator[] transmettra un objet de type Tableau<int>::erreur_indice qui sera reçu par la fonction main().

Page 61: Structures de données IFT-10541 Abder Alikacem Programmation orienté objet en C++ Module 2 Département dinformatique et de génie logiciel Édition Septembre

Le traitement des exceptions

Plusieurs catch peuvent apparaître après un try afin de recevoir et traiter plusieurs types d'erreurs.

L'expression catch(...) permet de recevoir tous les types d'erreurs non capturés par les catch précédents:

try{instructions

}catch(type 1){

instructions}catch(type 2){

instructions}catch(...){

instructions}