Vous êtes sur la page 1sur 90

COURS DE C++ partie 2

Approche oriente-objets - Notation UML Le langage C++ : aspects orients-objets


Jean BOURRELY ONERA/DPRS
Office National dtudes et de Recherches Arospatiales www.onera.fr

Programme : 1) Programmation oriente-objets : introduction quest-ce quun objet ? une classe ? une instance ? comment le modliser ? la notation UML : diagrammes de classes, relations entre classes syntaxe de dclaration des classes C++ : dfinition vs dclaration organisation classique des fichiers sources : .h et .cpp membres : attributs et mthodes dobjets le principe dencapsulation des donnes spcificateurs daccs : mots-cls private, protected, public manipulations des instances en tant que variables, accs aux attributs le cycle de vie dun objet : construction, utilisation et destruction les constructeurs : initialisation des instances les destructeurs : oprations de libration mmoire constructeurs spciaux : par dfaut, par copie, de transtypage 2) Programmation oriente-objets : complments dfinition de types dans une classe, classes imbriques mthodes constantes , protection des donnes le pointeur this listes dinitialisation de constructeur attributs constants, attributs rfrences et attributs objets tableaux dobjets attributs et mthodes de classe (static) reprsentation des associations UML : lien simple, agrgation, composition, multiplicit fonctions et classes amies (friend)

Approche oriente-objets
Pourquoi ce nom ?

Approche Approche OO OO

Approche centre sur les donnes : dcomposition structurelle du programme et non dcomposition fonctionnelle Donnes : ensembles dentits informatiques autonomes qui interagissent et communiquent entre elles Donnes = OBJETS

Une approche intuitive :


Dvelopper une application selon une approche objet, cest dfinir des classes et leurs mthodes associes Hirarchie verticale des classes : spcialisation : du plus gnral vers le particulier gnralisation ou factorisation : du concret vers labstrait Relations horizontales entre les classes liens dassociation liens dagrgation
Page 2

Notes :

Quest-ce quun objet ?

Approche Approche OO OO

Souvent, pour nous, lONERA cest un objet du monde rel, ce qui est trs plaisant :
Satellite

F-22 A3xx Radar Atmosphre Std76

Terre WGS84 Gravit

SCUD 1B
Page 3

Prcisions : Il sagit de quelques objets que jai eu le plaisir de modliser / instancier / dcrire / concevoir / coder, depuis 1998. Il est bien vident quun objet informatique nest pas toujours du monde rel, malheureusement !

Quest-ce quune classe ?


1) Vision ensembliste, mathmatique : Une classe est un ensemble dobjets [1] 2) Vision informatique : Une classe est un type (de donnes) [2]
Les deux visions se rejoignent :

Approche Approche OO OO

Une classe est un ensemble et un type de donnes, dont les lments sont apples instances. Les instances possdent : - des caractristiques dont les types sont semblables : les attributs - des comportements qui leur sont tous identiques : les mthodes
Avion EarthWGS84

UML
Page 4

Notes : [1] Ces objets, comme en mathmatiques les lments dun ensemble, possdent des caractristiques communes. [2] Dans ce sens, il ny a pas de diffrences entre la notion de classe int , float , Avion ou bien EarthWGS84 . UML : Ce que nous dit la spcification UML : A class is the descriptor for a set of objects with similar structure, behavior, and relationships. En UML, on reprsente graphiquement les classes par des rectangles, dans des diagrammes de classes.

Concepts de base de lapproche oriente-objets


Modlisation (classes, instances) Encapsulation Activation (mthodes, messages) Hritage (construction par affinage et factorisation)

Approche Approche OO OO

Page 5

Modlisation : elle comprend deux parties 1) Modlisation structurelle = ATTRIBUTS => Etat de lobjet => Liens avec dautres objets 2) Modlisation comportementale = METHODES => Rponses aux envois de message Encapsulation: Cest la protection que les objets accordent leurs attributs. Activation : Cest la capacit actionner un objet depuis lextrieur, par lappel de ses mthodes. Hritage : Cest la facult de capitaliser la modlisation structurelle et comportementale. Lhritage comprend deux aspects jumeaux : 1) la spcialisation : une sous-classe est cre partir dune super-classe pour rpondre un besoin spcifique 2) la gnralisation : une super-classe est cre partir de plusieurs classes pour y capitaliser tous leurs lments communs

Modlisation (1)
Modlisation structurelle :

Approche Approche OO OO

Propulsion - nom : String - debit : double - impulsionSpec : double - masseCarbu : double - sectionEject : double

UML

"bloc de dcollage" 7,45 Kg/s 185 s 29,8 Kg 0,1 m2 "bloc de croisire" 10,5 Kg/s 200 s 326 Kg 0,33 m2

Classe

Instances

Page 6

Notes : Une classe dcrit la structure (attributs) et le comportement (mthodes) des objets qui la composent. Chaque instance dune classe possde les mmes champs et les mmes mthodes que les autres. Mais les valeurs de ces champs peuvent varier dun objet lautre.

Modlisation (2)
Instance
"bloc de croisire" 10,5 Kg/s 200 s 326 Kg 0,33 m2 String : n octets double : 8 octets double : 8 octets double : 8 octets double : 8 octets

Approche Approche OO OO

Modlisation comportementale :
Propulsion - nom : String - debit : double - impulsionSpec : double - masseCarbu : double - sectionEject : double + resultante ( ) + consommationCarbu ( )

UML

lien vers les mthodes

Classe

Page 7

Notes : En mmoire de lordinateur, ce sont les attributs de chaque instance qui sont reprsents : il y a duplication des attributs pour chaque instance dobjet, mais pas des mthodes, qui sont du code commun toutes les instances de la classe.

Modlisation (3)
Diagram

Approche Approche OO OO

Structure Diagram

Behavior Diagram

Class Diagram Package Diagram

Composite Structure Diagram

Object Diagram

Activity Diagram

Use Case Diagram

State Machine Diagram

Component Diagram

Deployment Diagram

Interaction Diagram

Taxonomie des diagrammes UML


Sequence Diagram
Page 8

Communication Diagram

Interaction Overview Diagram

Timing Diagram

Notes : Sur la planche ci-dessus, on reprsente dans un diagramme de classes UML, les 13 diagrammes de la norme UML 2.0. Ceux dont le nom est en italique sont abstraits et nont pas de ralit concrte. Cest un exemple darbre dhritage du plus gnral (racine de larbre) au plus spcifique (les feuilles).

Encapsulation

Approche Approche OO OO

Les attributs sont la proprit de lobjet. En principe, on ne peut donc accder directement de lextrieur la valeur de ces champs. Cest lencapsulation. En contrepartie : Les mthodes d'une classe ont accs directement tous les attributs et toutes les autres mthodes de la classe.

"bloc de dcollage" 7,45 Kg/s 185 s 29,8 Kg 0,1 m2

Page 9

Notes : Chaque objet est libre de fournir ou non les informations quon lui demande : il peut les garder secrtes, effectuer des tests sur la demande, vrifier la qualit du demandeur, ... En pratique, la notion dencapsulation, trop contraignante, nest pas si strictement implante par les langages informatiques, et le C++ nchappe pas la rgle.

Activation

Approche Approche OO OO

Envoyer un message un objet cest lui demander de faire quelque chose, de fournir un rsultat. Lobjet est lunique destinataire du message. Traiter un message, cest appliquer la mthode associe, sur les arguments du message, dans le contexte de lobjet.

(Propulsion) bloc de croisire


n ur o t re
e nt a t l su re ()

Propulsion + resultante ( )

r eu t c ve

Mobile

Page 10

Explications : - Lobjet (instance) nomm bloc de croisire de la classe Propulsion possde une mthode qui sappelle resultante() . - Un autre objet, dune autre classe, la classe Mobile appelle la mthode en question. En retour, il reoit le rsultat du calcul.

10

Hritage (1)

Approche Approche OO OO

Cest la particularit la plus notable des langages objets. Chaque classe est sous-classe dune autre classe dont elle hrite les proprits. super classe

classe

sous classe Hritage de proprits : hritage des attributs (champs) de sa super classe hritage des mthodes de sa super classe
Page 11

Hritage / spcialisation : Une sous-classe est cre partir dune super-classe pour rpondre un besoin spcifique Avantages : rutilisation de code, extensibilit et remplacement de code (par masquage) Hritage / gnralisation : Une super-classe est cre partir de plusieurs classes pour y factoriser leurs proprits. Avantages : capitalisation, pas de duplication de code, constitution dinterfaces plus simples, communes des comportements divers.

11

Hritage (2)
Atmos

Approche Approche OO OO

La classe Atmos est une + calcul(alti : double, temp : double, press : double) gnralisation de 3 sousmodles datmosphre.

Atmos_St d76

Atmos_Kourou

Atmos_NOAA

Mobile3DDL # pos : DVector # vit : DVector

Avion - cap : double - pente : double + integrerMouvement(t : double)


Page 12

La classe Avion est une spcialisation de la classe des mobiles 3 degrs de libert.

Notes : Les relations dhritage entre les classes forment un graphe orient, non cyclique : le graphe dhritage. Si une classe peut hriter de plusieurs autres, on parle dhritage multiple, sinon dhritage simple. Lhritage multiple est autoris en C++, interdit en JAVA. Il prsente des avantages, mais doit tre mani avec prcaution. Dans le cas de lhritage simple, le graphe dhritage se rduit un arbre.

12

Hritage (3)

Approche Approche OO OO

Quand on rflchit, et les concepteurs de langages comme Java, C++, Ada95, Eiffel ou Smalltalk rflchissent, lhritage est une notion qui soulve de nombreuses questions : Hrite t-on toujours toutes les proprits de sa super classe ? [1] Y a t-il plusieurs formes dhritage ? [2] Que se passe t-il si une classe dfinit un attribut de mme nom quun attribut de sa super classe ? [3] Et la question la plus importante : quelle mthode est active, quand une classe et une sous-classe dfinissent une mthode de mme nom ? [4]

Page 13

Notes : [1] Oui/Non : a dpend du langage. Pour certains langages il ny a hritage que des attributs. [2] Oui/Non : a dpend du langage. Il ny a quune forme en Java par exemple, il y en a trois en C++. [3] Cest interdit // lattribut de la super-classe est cras // il y a duplication : a dpend du langage. [4] Voir planche suivante.

13

Lhritage et la question de lactivation

Approche Approche OO OO

Que se passe t-il si une classe dfinit une mthode de mme nom quune mthode de sa super classe ? cest le polymorphisme, mcanisme prvu par les modles objet en principe, la mthode de la classe est applique, elle remplace la mthode de la super classe en fait, a dpend du langage : typage statique ou typage dynamique

Simulation de deux classes (mobiles propulss MP, et non-propulss MNP) : MNP1 MNP2 MP1 MNP3 MP2

L : Liste<Mobile> m : Mobile Pour tout m de L : m -> integrerMouvement (pas) m -> resultanteForces ( )


Page 14

Notes : En Java, en Smalltak et dans lesprit de lapproche oriente-objet, le typage doit tre dynamique. Le programme dtermine lexcution quelle est la mthode appeler. Comme ce peut tre coteux en temps de calcul, le C++ a choisi le typage statique (i.e. la compilation), mais laisse lutilisateur la possibilit de choisir le typage dynamique (mthodes dites virtuelles, associes au mot-cl virtual). En plus dtre plus efficace, le typage statique est plus robuste : il permet de dtecter de simples erreurs de programmation ds la compilation.

14

Quest-ce quun attribut dobjet ?


Donne dun certain type qui est prsente dans chaque objet de la classe. [1] Synonymes : champs , donnes membres Le type de lattribut est le mme pour toute la classe. Les valeurs sont particulires pour chaque objet. [2] Lensemble des attributs forment ltat dun objet (partie structurelle). [3] Exemple : les attributs dun avion sont sa masse et ses caractristiques arodynamiques sera reprsent par :

Avion - masse : double - cx : double - cz : double

UML
Page 15

Notes : [1] Le terme dobjet dans lexpression attribut dobjet nest pas neutre. Nous verrons plus loin la notion dattribut de classe . Au lieu dattributs dobjets on parle aussi dattributs dinstances (le pluriel a son importance). [2] Si vous avez suivi : type gale classe , donne gale objet gale instance . Donc; on aurait pu dire quun attribut dobjet est une instance dun classe. [3] Autrement dit, dans un programme, pour sauvegarder un objet, il suffit de sauvegarder lensemble des valeurs des attributs de lobjet. En JAVA, cette opration a un nom, car elle est standardisable, on appelle cela la srialisation , on dit dun objet qui a cette capacit quil est Serializable. UML : En UML, on reprsente graphiquement les attributs dans un rectangle, sous celui qui porte le nom de la classe. Noter lordre en UML : "nom de la variable" + ":" + "nom du type"

15

Attributs : reprsentation UML (1)


En notation UML, on peut aussi reprsenter un attribut par un lien daggrgation :
-cx Avion - masse : double 1 -cz double 1 double

Mais cette notation est plutt rserve aux attributs de types complexes . Les attributs de types simples tant laisss dans le rectangle de la classe :
Aerodynamique - cx : double 1 - cz : double

Avion - masse : double

-aero

Lire : La classe Avion possde un attribut nomm aero dont la classe est Aerodynamique
Page 16

UML : Un lien daggrgation se reprsente avec une flche oriente vers le contenu. Du ct du conteneur, un losange plein. Optionnellement, on peut indiquer le nom de lattribut et la multiplicit. Note : Ici, on cre une nouvelle classe Aerodynamique qui agrge toutes les donnes arodynamiques dun avion. On gagne en gnricit : 1) la modification de larodynamique ne modifie pas la classe avion; 2) la classe Aerodynamique pourra tre rutilise par dautres objets ( Missile par exemple).

16

Attributs : reprsentation UML (2)


Entre attributs simples et complexes , tout est question dapprciation. Par exemple si on ajoute la spcification : ltat dun avion est aussi caractris par un vecteur position et un vecteur vitesse .

Aerodynamique -aero Avion - masse : double - cx : double - cz : double 1 DVector 1 DVector

Avion - masse : double - pos : DVector - vit : DVector

-pos -vit

-aero Aerodynamique - cx : double 1 - cz : double

La surcharge nous guette

Mieux, mais cest tout personnel

Page 17

Strictement la mme chose

Note : Pour moi, par exemple, sont des types simples : - les vecteurs, matrices - les nombres complexes (classe complex ) - les fichiers dentres-sorties, les flux - les chanes de caractres (classe std::string )

17

Classes : premire syntaxe C++ (1)


La dfinition d'une classe dbute par l'un des mots cls rservs : class, struct ou union. Par la suite, on traitera surtout le cas des classes et des structures. Tout ce qui est dit sur les classes s'applique aux structures (sauf indication contraire). Les unions restent un cas part. class Point { double x, y; int numero; double norm(); }; }; struct Point { double x, y; int numero; double norm();

Dfinitions (presque) identiques, sauf pour les droits d'accs.


Page 18

Syntaxe de base : le mot-cl class le nom de la classe (un symbole) accolade ouvrante plusieurs : - dfinitions dattributs : nom de type + nom de variable - dclarations de mthodes : fonctions qui sont connues par la classe accolade fermante point-virgule Note : Exple_48_classes Loubli du point-virgule est une erreur classique : class Point { } // error 'Point' followed by 'void' is illegal (did you forget a ';'?) void main() { }

18

Classes : premire syntaxe C++ (2)


// Une classe vide class JeSuisVide { }; // Une classe sans nom class { // donnees // fonctions // droits d'acces } x, *px, tab[10];

Mais ce sont des cas particuliers (pas forcment accepts par tous les compilateurs). Une classe n'est gnralement pas vide et elle a un nom. Il est aussi assez rare dexploiter la possibilit quoffre le langage de dfinir des variables la vole au moment de la dfinition de la classe (entre la dernire accolade et le point-virgule).
Page 19

Exemple : Exple_48_classes Exercice : Exple_49_Kp Syntaxe Que dfinissons-nous par linstruction suivante (autrement dit : que sont les diffrents "K" et "p" ?) : class K {K* p;} (*p) () ; 1) Souvenez-vous de la rgle de lescargot 2) Rcrivez tout cela sur plusieurs lignes 3) Creusez-vous les mninges ! Avant de savoir coder, il faut savoir relire du C++ ! 4) Non ce nest pas un exercice inutile et futile, il y a des fous qui peuvent crire comme a

19

Classes : de UML C++


Quand on passe au codage, on voit bien que les notions dattribut et daggrgation en UML sont identiques. En pratique
Avion - masse : double - cx : double - cz : double

class Avion { double masse; double cx, cz; };

Avion - masse : double - pos : DVector - vit : DVector

-aero Aerodynamique - cx : double 1 - cz : double

class Avion { double masse; DVector pos; DVector vit; Aerodynamique aero; }; class Avion { double masse; DVector pos; DVector vit; Aerodynamique* aero; };

Page 20

Explications : Lattribut aero est un objet de la classe Aerodynamique dans le premier cas, un pointeur dans le second. On choisit en effet parfois dimplmenter les agrgations vers des grosses structures par des pointeurs. Cela est mme absolument ncessaire si la structure en question est polymorphe , cest--dire sil y a possibilit dhritage : si Aerodynamique est une classe qui possde deux sous-classes : - AeroSimple avec des attributs cx, cz qui sont des nombres rels - AeroComplex avec des attributs cx, cz qui sont des tables dinterpolations si le type dfinitif ne sera connu qu lexcution en lisant le fichier de donnes par exemple, alors : Lutilisation du pointeur pour reprsenter lattribut aero est obligatoire Tout cela complexifie les chose. Qui a dit que ce serait simple ?

20

Attributs : dtails de syntaxe en C++


Il nest pas possible de dfinir un attribut dont le type est celui de la classe que lon dfinit. Il est en revanche possible de dfinir un attribut de type pointeur vers la classe en question. Il nest pas non plus possible de donner des valeurs par dfaut lors de la dfinition de la classe (cest de la syntaxe JAVA, pas C++). class Point { double x, y; int numero; }; 1 class Point { double x, y; Point autre; }; class Point { double x, y; Point *autre; }; 3

// ERREUR

class Point 2 { double x, y; int numero = 0; // ERREUR };


Page 21

// OK

Note : En Java, les notions de dclarations et de dfinitions nexistent pas. On donne toute la dfinition de la classe dans un fichier, les attributs ple-mle avec les mthodes. Bien sr, rien ntant libre, le fichier Java porte (obligatoirement) le nom de la classe et lextension .java . En C++ o tout est plus libre, les fichiers portent les noms et les extensions que lon veut.

21

Quest-ce quune mthode dobjet ?


Les mthodes dobjet (ou dinstance) sont des fonctions quil est possible dappliquer un objet dune classe. [1] Synonymes : fonctions membres ou simplement mthodes . Lensemble des mthodes forment la partie comportementale (dynamique) dun objet).

Avion - masse : double - pos : DVector - vit : DVector + Avion(f : FILE*) + ~Avion() + deplacer(dt : double) Aerodynamique -aero - cx : double - cz : double 1 + calculerForce(vit : DVec tor) : DVector

UML
Page 22

Prcisions : Petit rappel : en notation UML, on inverse tout par rapport au langage. On met en premier le nom des variables ou des arguments, et on met en dernier les types des valeurs de retour des fonctions. Avion(FILE* f) : cest une mthode spciale, un constructeur ~Avion() : galement une mthode spciale, un destructeur void deplacer(double dt) : mthode qui prend en argument un nombre rel DVector calculerForce(DVector vit) : mthode qui prend un vecteur et retourne un vecteur Notes : [1] Comme pour les attributs, le terme dobjet nest pas anodin. Une mthode dobjet (ou dinstance) sapplique un objet prcis, unique.

22

Mthodes dobjets : syntaxe C++


Comme dhabitude, il faut distinguer les notions de dfinition et de dclaration. On peut procder de deux manires pour introduire une mthode dans une classe : dfinir la fonction au sein de la dfinition de la classe elle-mme ; dclarer la fonction dans la classe, et la dfinir ailleurs. [1]

EN GENERAL : on dfinit la classe et on dclare ses mthodes dans un fichier dont le nom est celui de la classe et portant lextension .h [2] on dfinit les mthodes (leur corps) dans un fichier dont le nom est aussi celui de la classe et portant lextension .cpp qui inclut le prcdent

Page 23

Notes : [1] Personnellement, je naime pas dfinir la fonction au sein de la dfinition de la classe. Comme dhabitude, le C++ nous laisse une grande libert et chacun fait ce quil veut. Il faut de la pratique pour se faire sa philosophie du C++. Je connais quelquun lONERA qui met 80% des dfinitions des mthodes directement dans la classe. Pour conclure cette remarque, je propose la rgle suivante : - en premire approximation, on ne met pas le corps des mthodes dans la dfinition de la classe - on ne le fait la rigueur que pour les petites mthodes (accesseurs) ou que si on est press. [2] Toutes ces rgles de nommage ne sont que des conventions, dailleurs adoptes par JAVA et riges en rgle !

23

Organisation classique des fichiers


Mthode 1
Fichier Point.h class Point { double x, y; int numero; void setNumero (int n) { numero = n; } double norm() { return sqrt(x*x + y*y); } }; Fichier Point.h class Point { double x, y; int numero; void setNumero (int n); double norm(); };

Mthode 2
Fichier Point.cpp void Point::setNumero (int n) { numero = n; } inline double Point::norm() { return sqrt (x*x + y*y); }

Page 24

Notes : Lorsque la fonction est dfinie au sein de la classe, elle est implicitement mise en ligne ("inline"). Ainsi, dans la mthode 1, les deux mthodes sont inline . Dans la mthode 2, il faut mettre explicitement le mot-cl. Dans la mthode 2, la plus classique, il faut indiquer le nom de la classe suivi de (::) avant le nom de la mthode dont on donne le corps

24

Dfinition vs Dclaration
Dfinir une classe :
class Point { double x, y; int numero; double norm(); }; Fichier Point.h

Dclarer une classe :


class Point; Point *ptr_p; ptr_p = new Point;

Dclarer une classe c'est annoncer son existence sans pour autant spcifier son contenu (pas de #include "Point.h"). Une classe dclare peut tre utilise dans toute expression qui ne ncessite pas de connaissance de son contenu ou de ses fonctions.

Page 25

Explications : Dans lexemple de la planche, linclusion du fichier (#include "Point.h") est inutile, car le code na besoin que de dclarer un pointeur. Je reconnais que par paresse, on ne fait pas leffort de se poser toujours la question de lutilit dune inclusion. Dans un gros code, on gagne pourtant ainsi du temps la compilation en rduisant les dpendances entre les fichiers.

25

Exemple rcapitulatif sur les include


C1.h
#ifndef C1_H #define C1_H class C1 { ... }; #endif

C1.cpp
#include "C1.h" //Dfinitions //des mthodes //de la classe C1

C2.h
#ifndef C2_H #define C2_H class C1; class C2 { C1 *obj; }; #endif

C2.cpp
#include "C1.h" #include "C2.h" //Dfinitions //des mthodes //de la classe C2 //Utilisent C1

C3.h
#ifndef C3_H #define C3_H #include "C1.h" class C2; class C3 { C2 *obj2; C1 obj1; }; #endif

C3.cpp
#include "C2.h" #include "C3.h" //Dfinitions //des mthodes //de la classe C3 //(Utilisent C1) //Utilisent C2

Page 26

Explications : Le fichier C1.h contient la dfinition de la classe C1 Le fichier C1.cpp contient la dfinition des mthodes de C1, il inclut C1.h Le fichier C2.h contient la dfinition de la classe C1 et une dclaration de C2, ncessaire cause de lattribut pointeur vers C1 Le fichier C2.cpp contient la dfinition des mthodes de C2, celles-ci doivent utiliser les mthodes et/ou les attributs de C1 Le fichier C3.h contient la dfinition de la classe C3, une dclaration de C2 ( cause de lattribut pointeur) et une inclusion de C1.h ( cause de lattribut-objet). Le fichier C3.cpp contient la dfinition des mthodes de C3, celles-ci utilisent les classes C1 et C2, mais seulement linclusion de C2.h est ncessaire, car celle de C1.h se trouve dj dans C2.h

26

Notion dencapsulation (1)


Cest une bonne pratique de protger les donnes des objets pour respecter le principe de lencapsulation. [1] Un problme : Le C++ ne vrifie pas les droits daccs des mthodes lexcution, mais la compilation, sur la base des noms[2] : La question que se pose le langage : est-ce que la mthode Point::norm() peut accder aux attributs Point::x et Point::y ? et non : est-ce que la mthode norm() dans le contexte de linstance p peut accder p.x et p.y ?

Voir exemple Exple_50_encapsulation

Page 27

Notes : [1] Lencapsulation est une notion fondatrice de lapproche oriente-objets. Cest elle qui garantit la modularit des programmes. Dans lesprit le plus pur de lapproche objet, les attributs seront donc dclars privs (private), nous verrons plus loin cette notion. [2] Cest le choix du langage : le typage est statique, par dfaut.

27

Notion dencapsulation (2)


Lors de lexcution, les attributs de lobjet ne doivent tre accessibles ( porte ) que de lintrieur de lobjet : class Point { double x, y; int numero; double norm(); public: void show(); }; double Point::norm () { return sqrt (x*x + y*y); } void Point::show std::cout << " << " << " << " }
Page 28

Fichier Point.h

Fichier Point.cpp

() { X =" Y =" N =" Norm

<< << << ="

x x numero << norm();

Explications : Exple_51_point On voit apparatre un nouveau mot-cl public dans lexemple. Il signifie que tout ce qui suit est de porte gnrale et peut tre appel depuis nimporte quel endroit dans le code. Les deux mthodes ont accs tous les attributs quels quils soient. Enfin, une mthode peut appeler nimporte quelle autre mthode de la mme classe, quelle quelle soit.

28

Syntaxe complte de dfinition dune classe


Un parmi : class, struct, union Un parmi : private, protected, public

mot_rserv [nom_classe] [: specif super_classe]

{
[spcificateur_d'accs: [dfinitions_donnes] [dfinitions_fonctions] [dfinitions_types]] ...

Un parmi : private, protected, public

Un parmi : private, protected, public

[spcificateur_d'accs: [dfinitions_donnes] [dfinitions_fonctions] [dfinitions_types]] ... } [nom_objet1, nom_objet2, ...];

Page 29

Explications : Les lments entre crochets sont facultatifs.

29

Spcificateurs daccs (1)


Les spcificateurs private, protected et public peuvent apparatre dans un ordre et un nombre quelconque dans la dfinition d'une classe. Un spcificateur dfinit les rgles d'accs applicables jusqu'au spcificateur suivant. class Point { private: double x, y; int numero; public: void setNumero (int n); protected: Point *suivant; double norm(); public: void show(); };
Page 30

Notes : Comme dhabitude tout est libre en C++, mais chaque programmeur arrange les attributs et les mthodes dans un ordre qui lui convient. Personnellement, jaime bien : 1) mettre les attributs en premier : aucun nest public pour respecter le principe de lencapsulation 2) je mets ensuite les constructeurs et destructeurs 3) puis les mthodes public 4) enfin les mthodes private et protected Dautres prfreront mettre tout ce qui est public au dbut, le reste ensuite. Car pour eux lutilisateur de la classe doit connatre en priorit la partie publique et se moque des attributs privs. Cest un autre point de vue, parfaitement respectable.

30

Spcificateurs daccs (2)


Si aucun spcificateur n'est prcis : les membres sont privs (private) par dfaut pour une classe (class) ; ils sont publics (public) par dfaut pour une structure (struct). class Point { double x, y; int numero; public: void setNumero (int n); double norm(); }; Trois donnes prives Deux mthodes publiques struct Point { double x, y; int numero; void setNumero (int n); double norm(); }; Tout est public

Page 31

Notes : En C, les structures nont pas de mthodes, il sagit bien entendu dun ajout du C++. En C++, les structures ne sont plus tellement employes, elles sont conserves pour des raisons de compatibilit avec le C.

31

Spcificateurs daccs (3)


Spcificateur private L'accs aux donnes et fonctions prives d'une classe (private) est rserv aux mthodes de la classe elle-mme, ainsi qu' des fonctions ou des classes trangres dclares amies (friend).

private par dfaut

class Point { double x, y; int numero; public: void setNumero (int n); double norm(); };

Seules les mthodes setNumero et norm de la classe Point peuvent accder aux variables x, y, et numero. Le programmeur est sr qu'aucune autre partie du programme ne peut ni les lire, ni les modifier.

Page 32

Notes : Un petit conseil : il vaut mieux mettre le mot-cl private , plutt que de ne rien mettre et laisser laccs par dfaut. UML : Un membre priv (attribut ou mthode) est prcd du signe moins (-). Cf. exemple planche suivante.

32

Spcificateurs daccs (4)


Spcificateur protected Le spcificateur protected a un effet semblable private, mais avec une limitation moins svre des accs. En effet, l'accs est galement autoris aux mthodes des sous-classes et aux amis de ces sous-classes.
Mobile3DDL # pos : DVector # vit : DVector

Avion - cap : double - pente : double + integrerMouvement(t : double)

La classe Avion possde une mthode integrerMouvement qui peut accder tous les attributs de la classe et de sa super-classe.

Page 33

UML : Un membre protg (attribut ou mthode) est prcd du signe dise (#). Le code de lexemple : class Mobile3DDL { protected: DVector pos; DVector vit; }; class Avion : Mobile3DDL { private: double cap; double pente; public: void integrerMouvement(double t); };

33

Spcificateurs daccs (5)


Spcificateur public Le spcificateur public signifie que la mthode ou l'attribut est accessible depuis n'importe quelle autre fonction du programme. Pour respecter l'esprit de la programmation objet, il faut cependant viter de rendre publics des attributs.
Nom de la classe - attribut_priv : Type - attribut_priv : Type = valeur # attribut_protg : Type # attribut_protg : Type = valeur + attribut_public : Type + attribut_public : Type = valeur - mthode_prive() - methode_prive(argX : TypeX) - mthode_prive() : TypeY # mthode_protge() + mthode_publique()
Page 34

Rcapitulatif UML

UML : Un membre public (attribut ou mthode) est prcd du signe plus (+).

34

Accs aux attributs et mthodes ( membres )


On accde aux attributs et aux mthodes d'un objet par la notation pointe (ou la notation flche dans le cas d'un pointeur sur un objet : Fichier Point.h class Point { public: double x, y; int numero; void setNumero (int n); double norm(); void show(); }; } Fichier Main.cpp int main() { Point pa; Point *pb = new Point; Point tp[3]; pa.x pb->x tp[0].x tp->x ... ... ... ... = = = = = = = = ... ... ... ...

pa.norm(); pb->norm(); tp[0].norm(); tp->norm();

Page 35

Explications : 1) Par souci de simplicit, on a dclar tous les membres publics. 2) pa est du type Point , on accde ses attributs et appelle ses mthodes par la notation pointe. 3) pb est du type pointeur vers Point , on utilise la notation flche 4) tp[0] est du type Point , notation pointe 5) tp est du type pointeur vers Point , notation flche

35

Encapsulation : notion daccesseurs


Pour respecter le principe dencapsulation des donnes, on ne rend pas les attributs publics [1]. Si leur accs est ncessaire, une bonne pratique consiste le faire par des mthodes. Ces mthodes sappellent des accesseurs (setters/getters en anglais). Si x est un attribut de type Type : void setX(const Type& _x) {x = _x;} const Type& getX() {return x;} Ces mthodes tant de petite taille, elles sont gnralement dclares en ligne ( inline ), ce qui les rend galement plus efficaces.
Nom_Clas se - x : Type - y : double + + + + setX(_x : const Type&) getX() : const Type& setY(_y : double) getY() : double

Page 36

Notes : [1] Le langage nimpose rien, cest juste une bonne pratique commune aux programmeurs. Explications : Noter lutilisation du mot-cl const : - dans le setter : il indique quon ne modifiera pas la variable en argument qui sera recopie - dans le getter : le fait de retourner une rfrence constante, empche de la modifier Si lattribut est dun type simple, on nutilise pas forcment le passage par rfrence : void setY (double _y) {y = _y;} double getY() {return y;} Une proposition intressante : Je connais quelquun qui aime bien utiliser comme noms des accesseurs le nom mme de lattribut, exploitant ainsi la surcharge des noms de fonctions : class C { Type attr; public: void attr(const Type& _a) {attr = a;} const Type& attr() {return attr;} };

36

Manipulation des instances (1)


On cre une nouvelle instance d'une classe, comme on cre une nouvelle variable d'un type donn : #include "Point.h" { ... int i; int *j; j = &i; int *k; k = new int; int tab[10]; ... } nouvel objet pointeur { ... Point p; Point *q; q = &p; Point *r; r = new Point; Point tabPoints[10]; ... }

pointeur+allocation tableau

Page 37

Notes : Il ny a pas de difficult se mettre dans la tte les quivalences suivantes : CLASSE = TYPE INSTANCE (OBJET) = VARIABLE

37

Manipulation des instances (2)


En plus de l'accs aux attributs et aux mthodes par les notations pointe et flche, on peut utiliser les actions suivantes sur un objet : connatre son adresse : &p connatre sa taille : sizeof(p) utiliser l'affectation membre membre : p1 = p2 #include "Point.h" Le compilateur cre automatiquement un oprateur d'affectation = par dfaut, dans la mesure o le programmeur ne s'en charge pas. Cet oprateur par dfaut ne fonctionne que pour des objets de mme classe (pas de conversion implicite). { ... Point p1; Point p2; ... p2 = p1; ... }

Page 38

Exercice : Exple_52_instances Dfinir dans les rgles de lart une classe Point , avec les attributs et mthodes des exemples prcdents. Afficher la taille dune instance de cette classe laide de loprateur sizeof() Dclarer un pointeur vers Point et lui donner une valeur alloue dynamiquement (new) Afficher la taille du pointeur avec sizeof() Afficher la taille de lobjet point (utiliser lindirection *) Dclarer une nouvelle variable Point et un nouveau pointeur et vrifier si laffectation fonctionne laide de loprateur (=), contrler les tailles des copies, afficher leurs valeurs. Accder aux attributs et aux mthodes avec la notation pointe et flche. On peut facultativement dfinir un tableau de Point , et sentraner les manipuler Ne pas oublier de dtruire (delete) tout ce qui a t allou dynamiquement

38

La vie dun objet


Allocation de la mmoire ncessaire pour stocker les donnes de l'objet Construction (= initialisation et ventuellement allocation de mmoire pour les objets contenus ou points)

AUTOMATIQUE

CONSTRUCTEUR

Utilisation

4 5

Destruction (dsallocation de mmoire des objets contenus ou points)

DESTRUCTEUR

Dsallocation de la mmoire occupe par les donnes de l'objet

AUTOMATIQUE

Page 39

Notes : La vie dun objet dure autant que sa porte : - Une variable globale dure du dbut la fin du programme. - Une variable locale dure dans le bloc dont elle dpend { }. - Un objet allou dynamiquement dure tant quil nest pas dtruit (encore faut-il ne pas perdre son adresse pour pouvoir le dtruire le moment voulu.

39

Constructeurs et destructeurs
Les constructeurs et les destructeurs sont les mthodes les plus importantes d'une classe. C'est l que se concentrent les erreurs les plus graves : c'est l que sont cres toutes les donnes qui seront ensuite utilises dans le programme ; on y manipule allocation et dsallocation dynamique de la mmoire ; elles n'intressent gnralement pas le programmeur-ingnieur (pas de science).

Page 40

Notes : Cest dans les constructeurs que les dbutants perdent du temps de calcul. Sans prcaution, des constructeurs de classes vecteurs ou matrices peuvent occuper par exemple 80% du temps machine dune simulation type mcanique du vol .

40

Constructeurs (1)
Un constructeur est une mthode spciale qui est appele automatiquement juste aprs une cration dobjet. Il porte le mme nom que la classe, et n'a pas de type de retour. Un constructeur sert initialiser l'objet au moment de sa cration :
Fichier Point.h
class Point { double x, y; int numero; public: Point(int n); Point(double xx, double yy); };

Fichier Point.cpp
Point::Point (int n) { x = y = 0.0; numero = n; } Point::Point (double xx, double yy) { x = xx; y = yy; numero = 0; }

Il peut y avoir plusieurs constructeurs (surcharge de fonction).


Page 41

Notes : Nous verrons plus loin quil est plus propre de prendre lhabitude dutiliser ce que lon appelle les listes dinitialisation des constructeurs : Point::Point (int n) : x(0.0), y(0.0), numero(n) { }; Point::Point (double xx, double yy) : x(xx), y(yy), numero(0) { };

41

Constructeurs (2)
Lors de la dfinition de l'objet, les arguments du constructeur sont passs entre parenthses aprs le nom de l'objet : Point p1(10); Point p2(1.0, 2.0); On peut aussi utiliser le signe = suivi du nom du constructeur : Point p1 = Point(10); Point p2 = Point(1.0, 2.0); Dans le cas o une seule valeur d'initialisation est mentionne, il est possible d'omettre le nom du constructeur (constructeur de transtypage) : Point p1 = 10; Pour la cration d'objets dynamiques, le constructeur est prcd du mot-cl new : Point *p1 = new Point(10); Point *p2 = new Point(1.0, 2.0);
Page 42

Notes : Le constructeur Point(int n) est un peu spcial, cest un constructeur de transtypage : celui-ci transforme ( caste ) un entier en un Point ! Point p1 = 1; Point p2 = 2; Point p3(3); int i=4; Point p4 (i); Nous verrons, quil ne suffit pas faire des affectations : Point p5; p5 = 5; L il faut aussi dfinir loprateur (=) !

42

Constructeurs (3)
Paramtres par dfaut et constructeur sans argument
Fichier Point.h
class Point { double x, y; int numero; public: Point(double xx = 0.0, double yy = 0.0, int n = 0); }; #include "Point.h" { Point p1(1.0, 2.0, 10); // 3 args Point p2(1.0, 2.0); // 2 args Point p3(1.0); // 1 arg Point p4; Point p5(); // // // // // // 0 arg ERREUR ? Cest la dclaration dune fonction qui retourne un 'Point' // 0 arg

Il peut y avoir des paramtres par dfaut dans un constructeur.

Point P6 = Point(); }

Page 43

Notes : Grce aux arguments par dfaut, il y a donc 4 formes possible de construction pour la classe Point. La forme sans argument est spciale : il sagit de ce que lon appelle le constructeur par dfaut que nous verrons plus loin. La dernire forme : Point P6 = Point(); est inutilement verbeuse, aurait suffit : Point p6; Point p6 = Point; Pour lallocation dynamique : Point *pp1 = new Point(); Point *pp2 = new Point; // acceptable aussi

43

Constructeurs (4)
Les constructeurs sont soumis aux contraintes de droits d'accs spcifies par private, protected ou public. Pour permettre des sections de programmes de crer des objets, on rend le constructeur correspondant public. Mais parfois, on souhaite justement qu'aucun objet de cette classe ne soit cr (classe abstraite) et on protge ou on privatise le constructeur.
class Point { private: double x, y; int numero; Point(); // => Interdiction de lutiliser public: Point(double xx, double yy, int n); };
Page 44

Notes : Une classe abstraite est une classe quon ne peut instancier telle quelle (pas de constructeur public). En revanche, elle peut avoir des sous-classes instanciables qui ont besoin dutiliser les constructeurs de la super-classe. La solution est alors de les dclarer protgs ( protected ) dans la super-classe.

44

A quoi servent les constructeurs ? (1)


Initialiser les attributs d'un objet et allouer la place mmoire ncessaire pour les objets contenus et points : Fichier Avion.h class Avion { Vector3D position; Vector3D vitesse; double masse; Aerodynamique *aero; Propulsion *propu; public: Avion(); Avion(FILE* f); };
Page 45

Constructeur par dfaut, il doit initialiser les attributs des valeurs par dfaut (0, NULL).

Constructeur principal, il doit initialiser les attributs en fonction des valeurs lues dans un fichier.

Notes : Le terme constructeur est plutt inappropri, en fait en devrait parler d initialiseur .

45

A quoi servent les constructeurs ? (2)


Fichier Avion.cpp
Avion::Avion() { position.setZero(); vitesse.setZero(); masse = 0.0; aero = NULL; propu = NULL; } Avion::Avion(FILE *f) { position = readVector(f); vitesse = readVector(f); masse = readDouble(f); aero = new Aerodynamique(f); propu = new Propulsion(f); }
Page 46

Initialiser les valeurs des attributs.

Allouer dynamiquement les objets contenus.

Notes : Les tches les plus frquentes des constructeurs : 1) initialiser les valeurs des attributs 2) allouer dynamiquement les objets contenus 3) tablir les liens entre lobjet et les autres objets du programme

46

Constructeur par dfaut (1)


Un constructeur par dfaut est un constructeur que l'on peut utiliser sans lui passer de paramtres : il peut s'agir de constructeurs sans paramtre formel, ou de constructeurs qui ne comportent que des valeurs par dfaut. Point(); Point(double xx = 0.0, double yy = 0.0, int n = 0);

Avion();

Mais les rgles sur les surcharges de noms de fonctions empchent que plusieurs constructeurs par dfaut soit prsents : une classe ne doit comporter qu'un seul constructeur par dfaut. Si pour une classe on ne dfinit pas de constructeur (du tout), le compilateur en crera un, par dfaut, public, pour la construction d'objets. Ce constructeur ne ralise aucune initialisation et laisse les attributs de l'objet cr dans un tat indfini.
Page 47

Notes : Ce point est important : le compilateur cre un constructeur par dfaut public si le concepteur na dfini aucun constructeur. Dans la majorit des cas, on peut se contenter de ce constructeur. Mais si on veut initialiser des attributs ou si on doit allouer dynamiquement le contenu de lobjet, alors il faudra bien dfinir un ou des constructeurs. class Point { public: double x, y; int numero; }; void main() { Point p; // ca marche // warning local variable 'p' used without having been initialized std::cout << p.numero << " " << p.x << " " << p.y << std::endl; // Affiche : -858993460 -9.25596e+061 -9.25596e+061 }

47

Constructeur par dfaut (2)


class Point { double x, y; int numero; }; class Point { double x, y; int numero; public: Point(int n); }; class Point { double x, y; int numero; Point(); public: Point(int n); }; class Point { double x, y; int numero; Point(int n=0); };
Page 48

Le compilateur cret-il un constructeur par dfaut ?

Un constructeur Point() existe-t-il ? Quels sont ses droits d'accs ?

Exercice : Exple_53_constructeurDefaut

48

Constructeur par copie (1)


Un constructeur par copie est un constructeur qui permet d'initialiser un objet avec un autre objet de la mme classe. Il comporte un seul paramtre : une rfrence (constante) un objet de la classe laquelle il appartient.
Fichier Point.h
class Point { double x, y; int numero; public: Point(int n); Point(const Point &p); }; #include "Point.h" ... Point p1(1000); Point p2(p1); // constructeur par copie Point p3 = p1; // constructeur par copie Point *pp = new Point(p1); double norm(Point p); // idem

Le constructeur par copie est appel aussi pour transmettre un objet une fonction
Page 49

Petit rappel : Par dfaut, le C et le C++ utilisent la transmission par valeur des paramtres aux fonctions. Le passage par valeur implique que la donne transmise soit recopie localement par la fonction : cest la raison pour laquelle le constructeur de copie est automatiquement appel lors dun passage par valeur (et dun retour aussi !).

49

Constructeur par copie (2)


Si pour une classe on ne dfinit pas de constructeur par copie, le compilateur en crera un, par dfaut, public. Ce constructeur est trivial : il copie membre membre les attributs de l'objet copi dans le nouvel objet. Exemple :
Fichier Point.h
class Point { double x, y; int numero; public: Point(int n); Point(const Point &p); };

Fichier Point.cpp
Point::Point (int n) { x = y = 0.0; numero = n; } Point::Point (const Point &p) { x = p.x; y = p.y; numero = p.numero; }

Page 50

Notes : Dans les cas les plus simples, le constructeur par copie trivial suffira. Dans lexemple de la planche, le constructeur par copie qui a t crit est strictement le mme que celui que le compilateur aurait synthtis, ce qui rend le travail un peu inutile.

50

Constructeur par copie (3)


Exemple :
Fichier Avion.h class Avion { Vector3D position; Vector3D vitesse; double masse; Aerodynamique *aero; Propulsion *propu; public: Avion(const Avion&); }; Avion::Avion(const Avion& m) { position = m.position; // COPIE vitesse = m.vitesse; // COPIE masse = m.mass; if (m.aero != NULL) aero = new Aerodynamique(m.aero); // COPIE else aero = NULL; if (m.propu != NULL) propu = new Propulsion(m.propu); // COPIE else propu = NULL; } Fichier Avion.cpp

Ce nest plus aussi trivial. Chaque objet Avion doit avoir sa propre propulsion et arodynamique.
Page 51

Notes : Que se passerait-il si on faisant simplement : aero = m.aero; propu = m.propu; La conception UML de la classe Avion prcise quil y a un lien de composition entre cette classe et la classe Aerodynamique . Cest en crivant ce code de recopie, qui alloue sa propre arodynamique chaque instance davion que lon voit respecter la smantique de la composition.

51

Constructeurs de transtypage
Un constructeur de transtypage permet la transformation d'un objet d'un type en un autre. En fait, tout constructeur qui s'appelle avec un unique paramtre, d'un type autre que celui du constructeur est un constructeur de transtypage.
Fichier Point.h
class Point { double x, y; int numero; public: Point(); Point(int); Point(const Point&); }; #include "Point.h" ... Point p1;

// constructeur // par dfaut // constructeur // de transtypage

Point p2(10); Point p3 = 10;

Point p4(p2); // constructeur Point p5 = p2; // par copie Point *pp = new Point(p2);

Page 52

Notes :

52

Destructeur (1)
Les destructeurs sont les symtriques des constructeurs. On trouve dans un destructeur des tches qui sont du domaine du "nettoyage" : libration de la mmoire alloue dynamiquement ; enregistrement de donnes, fermeture de fichiers ... Le nom du destructeur est le mme que celui de la classe, prcd du signe tilde "~". Un destructeur ne possde pas de valeur de retour et n'a aucun argument.
class Point { double x, y; int numero; public: Point(int n); Point(double xx, double yy); ~Point(); };
Page 53

Grce la surcharge des noms de fonctions, il peut y avoir plusieurs constructeurs, mais il ne peut y avoir qu'un seul destructeur.

Notes : Si le concepteur ne cre pas de destructeur, le compilateur en cre un par dfaut, trivial : il ne fait rien. Un bon rflexe : Si la classe doit comporter des sous-classes, il vaut mieux prendre ds maintenant lhabitude de dclarer le destructeur virtuel , exemple : virtual ~Point(); Nous expliquerons pourquoi plus tard. En revanche, si la classe ne doit pas tre sous-classe, cest inutile (et peut mme nuire aux performances).

53

Destructeur (2)
Comme pour toutes les mthodes, la dfinition du destructeur peut se trouver dans la dfinition de la classe ou l'extrieur :
Fichier Avion.h class Avion { ... Aerodynamique *aero; Propulsion *propu; public: Avion(File* f); ~Avion() { if (aero != NULL) { delete aero; aero = NULL; } if (propu != NULL) { delete propu; propu = NULL; } } }; Fichier Avion.h class Avion { ... Aerodynamique *aero; Propulsion *propu; public: Avion(File* f); ~Avion(); };

OU

Fichier Avion.cpp Avion::~Avion() { if (aero != NULL) { delete aero; aero = NULL; } if (propu != NULL) { delete propu; propu = NULL; } }

Page 54

Notes :

54

Destructeur (3)
Dans l'immense majorit des situations, les destructeurs sont appels implicitement pendant l'excution du programme. Pour les objets crs dynamiquement, il faut cependant appeler explicitement la destruction sur le pointeur.
#include "Point.h" { Point p1; Point p2(10); Point *pp1 = new Point; Point *pp2; *pp2 = &p1; Point *pp3 = new Point(10); ... delete pp1; delete pp3; }
Page 55

Le destructeur est automatiquement appel pour les objets p1 et p2 l'accolade fermante. Il faut appeler le destructeur sur pp1 et pp3, mais pas sur pp2 qui pointe sur p1.

Notes :

55

Dfinition de types dans une classe (1)


En plus des attributs et des mthodes, une dfinition de classe peut comporter des dfinitions de type, par typedef, par enum, voire mme la dfinition d'une classe imbrique. Fichier Segment.h class Segment { private: class Point { double x, y; public: Point() {x=y=0.0;} }; public: typedef Segment* PTR; typedef unsigned int color; enum Status { visible, hidden }; };
Page 56

Classe imbrique

Nouveaux types

Notes : Comme pour les attributs et les mthodes, tous les lments qui sont dfinis dans une classe ont un nom (pour lextrieur) qui est celui de la classe suivi de (::), cf planche suivante. Donc, par exemple : - lextrieur de la classe : Segment::xxxxxx - lintrieur des mthodes de la clase Segment : seulement xxxxxx Exemple : Exple_56_imbrication

56

Dfinition de types dans une classe (2)


La classe englobante n'a aucun droit particulier sur la classe englobe, et inversement. Les types imbriqus sont soumis aux mmes rgles d'accs que les attributs et les mthodes. Leur nom doit tre prcd de celui de la classe : // error 'Point' : undeclared identifier Point p1; // error 'Point' : cannot access private class // declared in class 'Segment' Segment::Point p2; // error : 'PTR' : undeclared identifier PTR s1; Segment::PTR s2; Segment::color c = 1; // OK // OK

Segment::Status s = Segment::visible; // OK
Page 57

Notes : Lutilisation des classes imbriques est assez rare, plutt apprcie des experts, amateurs dexercices de style. En revanche, lintrt des typedef est le mme que dhabitude : dbrouiller les dclarations de types un peu compliques. Lutilisation de la dclaration des numrations est aussi assez frquent : - dans une classe systme dynamique on dfinit trois tats : created, running, stopped - dans une classe radar on dfinit trois formes dondes : beam, sphericalHarmonic, omniDirectional - dans une classe logique tendue on dfinit trois tats : vrai, faux, indtermin - Exemple : Exple_56_imbrication

57

Mthodes constantes (1)


Parmi les mthodes d'une classe, il est possible de distinguer : celles qui modifient les attributs d'un objet ; celles qui ne modifient aucun attribut ("mthodes constantes"). Les mthodes "constantes" ne font pas d'accs "en criture". Le mot rserv const doit figurer dans leur dclaration et dans leur dfinition, aprs la liste des arguments :
Fichier Point.h
class Point { double x, y; int numero; public: void setNumero (int n); double norm() const; };

Fichier Point.cpp
void Point::setNumero (int n) { numero = n; } double Point::norm() const { return sqrt (x*x + y*y); }

Important : const fait partie de la signature.


Page 58

Notes : Il ne faut pas confondre la syntaxe des mthodes constantes, avec la syntaxe des mthodes qui retournent un objet constant (que lappellant ne peut modifier) : const double& getX() {return x;} // Retourne rfrence constante double getX() const {return x;} // Mthode constante // Les deux

const double& getX() const {return x;}

Exemple : Exple_57_methodesConst

58

Mthodes constantes (2)


Les constructeurs et les destructeurs ne peuvent tre dclars const. Parmi les mthodes d'une classe, les mthodes constantes forment une classe d'quivalence : une mthode constante ne peut appeler que des mthodes constantes.
class Avion { Vector3D position; double masse; Aerodynamique *aero; public: Vector3D getPosition() const; void setPosition(Vector3D xyz); double getMasse() const; void setMasse(double m); const Aerodynamique* getAero() const; void setAero(Aerodynamique *a); };
Page 59

Les accesseurs sont des mthodes qui permettent de voir ou de modifier les attributs. Les accesseurs en lecture ("get") sont dclars const.

Notes : A un objet constant, on ne peut appliquer que des mthodes constantes : const Avion av; V = av.getPosition(); av.setPosition(V); // CORRECT // ERREUR

59

Protger ses donnes


Donner un accs protected ou private aux attributs, crire des mthodes accesseurs, utiliser les fonctions const sont les moyens utiliser pour protger les donnes d'un objet (encapsulation).
Fichier Point.h
class Point { private: double x, y; int numero; double norm() const; double diff(); public: void setNumero (int n); void show() const; };

S'il y a une erreur dans les donnes x, y ou numero, les seules mthodes mettre en cause sont les mthodes non constantes (diff et setNumero).

Page 60

Notes : Personnellement, je pense que prvoir les limitations daccs notamment par lutilisation des mthodes constantes, doit tre fait ds la phase de conception, dbut de la phase de codage. Tout ceux que je connais qui me disent je le ferai quand le code sera dans une version V0 , ne le font en pratique jamais.

60

Exercice : protection des donnes


Que pouvez-vous proposer pour scuriser la classe suivante ? class Machin { public : double truc; int machin; double calcule() {return truc*machin;} }; Attention, on prcise quil ne faut pas pour autant diminuer les possibilits daccs offertes lutilisateur de cette classe. Tester les modifications dans un petit programme.

Page 61

Exercice : Exple_58_protection Tous les moyens de protection tudis dans les planches prcdents doivent tre mis en uvre.

61

Le pointeur this (1)


Chaque mthode d'objet dispose en fait d'un argument supplmentaire, ajout automatiquement par le compilateur. Cet argument est un pointeur du nom de this, vers l'objet qui est appliqu la mthode.
Fichier Point.h
class Point { private: double x, y; int numero; public: void setNumero (int n); void show() const; double norm() const; };

Fichier Point.cpp
void Point::setNumero (int n) { this->numero = n; } void Point::show() { cout << "Adresse << "\nX << "\nY << "\nNorm } const : : : : " " " " << << << << this this->x this->y this->norm();

Dans cet exemple, tous les "this->" sont optionnels.


Page 62

Exemple : Exple_59_this

62

Le pointeur this (2)


this est un pointeur constant dont la valeur est l'adresse de l'objet. L'intrt du pointeur this se fait sentir dans au moins deux cas : lorsque les attributs de l'objet sont masqus par des dclarations qui utilisent les mmes noms : Point::Point(double x, double y) { this->x = x; this->y = y; } lorsqu'on veut retourner l'adresse de l'objet : Point* selfPtr() { // Je fais des trucs et je retourne mon adresse return this; }

Page 63

Notes : Similaire au cas o on veut retourner ladresse de lobjet, il y a le cas o on veut retourner une rfrence constante ou non sur lobjet : Point& selfV() {return *this;} const Point& selfC() const {return *this;} Exemple : Exple_59_this

63

Liste dinitialisation de constructeur (1)


La dfinition d'un constructeur peut comporter, en en-tte, ce qu'on appelle une liste d'initialisation de constructeur, qui figurerait sinon dans le corps.
Fichier Point.h
class Point { double x, y; int numero; public: Point(int n); Point(double xx, double yy); };

Fichier Point.cpp
#include "Point.h" Point::Point(int n) : x(0.0), y(0.0), numero(n) {} Point::Point (double xx, double yy) : x(xx), y(yy), numero(0) {}

La liste est introduite par deux points (:) et comporte des couples noms d'attributs - valeur. Chaque attribut ne peut apparatre au maximum qu'une seule fois.

Page 64

Notes : Cest une bonne habitude dutiliser systmatiquement les listes dinitialisations, plutt que de faire les initialisations dans le corps du constructeur. Pourquoi ? Ne serait-ce que pour des raisons de performance : sans cela un constructeur par dfaut est appel pour chaque attribut, puis un oprateur daffectation (=).

64

Liste dinitialisation de constructeur (2)


Les valeurs d'initialisation ne se limitent pas aux constantes, il peut s'agir d'expressions complexes :
Fichier Polynom.h class Polynom { int degre; double *coeff; public: Polynom(); Polynom(int n); Polynom(const Polynom &p); }; Fichier Polynom.cpp #include "Polynom.h" Polynom::Polynom() : degre(0), coeff(NULL) {} Polynom::Polynom(int n) : degre(n), coeff(new double[n+1]) {} Polynom::Polynom(const Polynom &p) : coeff(new double[degre+1]), degre(p.degre) { for (int i=0; i<=degre; i++) coeff[i] = p.coeff[i]; }

L'ordre importe peu dans la liste d'initialisation. Ce qui compte c'est l'ordre des attributs dans la dfinition de la classe.

Page 65

Explication : Dans lexemple ci-dessus, lattribut degre est dfini avant coeff dans la dfinition de la classe (fichier "Polynom.h"). Cest donc dans cet ordre que sont initialiss les attributs dans la liste dinitialisation. En particulier, on voit que la liste du 3me constructeur est valide, mme si elle donne limpression que degre nest pas encore initialis lors de lallocation dynamique de coeff . Exemple : Exple_60_polynom

65

Liste dinitialisation de constructeur (3)


Dans certains cas, la liste d'initialisation n'est pas une simple alternative, elle doit tre obligatoirement utilise : initialisation d'attributs constants; [1] initialisation d'attributs rfrences; [2] initialisation d'attributs objets. [3]

Page 66

Notes : [1] Cest--dire dattributs qui sont dclars const . [2] On rappelle que les rfrences doivent tre initialises une valeur lors de leur dfinition, et que cet alias ne peut tre dplac par la suite. [3] Il sagit dattributs qui sont des objets de classes pour lesquelles il nexiste pas de constructeur par dfaut (cf. planches suivantes).

66

Attributs constants
Il est possible de dclarer constants (const) les attributs d'un objet. Durant la vie de l'objet, ceux-ci ne pourront changer. [1] Les attributs constants doivent tre initialiss dans la liste d'initialisation du constructeur.
Fichier Avion.h class Avion { Vector3D position; Vector3D vitesse; double masse; const double sRef; const double coeffAxial; public: Avion(); Avion(double s, double ca, double m, Vector3D pos, Vector3D vit); }; Fichier Avion.cpp Avion::Avion() : masse(0.0), sRef(0.0), coeffAxial(0.0) { position.setZero(); vitesse.setZero(); } Avion::Avion(double s, double ca, double m, Vector3D pos, Vector3D vit) : position(pos), vitesse(vit), masse(m), sRef(s), coeffAxial(ca) { }

Page 67

Notes : [1] Cest la raison pour laquelle leur initialisation ne peut avoir lieu dans le corps du constructeur. En effet un constructeur est une mthode comme une autre; lorsquon lappelle, la vie de lobjet a dj commence. Petit rappel : une constante doit tre initialise lors de sa dclaration. Exemple : // error : 'i' : const object must be initialized if not extern const int i; i = 0;

67

Attributs rfrences
Il est possible de dclarer des attributs qui soient des rfrences. Ces rfrences ne peuvent tre initialises leur dclaration (comme le veut le cas gnral). [1] Les rfrences doivent tre initialises dans la liste d'initialisation du constructeur, elles ne peuvent tre changes par la suite.
Fichier Avion.h
class Avion { Vector3D position; Vector3D vitesse; double masse; Aerodynamique &aero; Propulsion &propu; public: Avion(Aerodynamique &a, Propulsion &p); };
Page 68

Fichier Avion.cpp
Avion::Avion(Aerodynamique &a, Propulsion &p) : aero(a), propu(p) { }

A viter et utiliser les pointeurs [2] : - on peut changer d'objet point ; - on peut grer le cas par dfaut avec NULL.

Notes : [1] Au cause de la syntaxe C++ qui interdit dcrire : class Point { int numero = 0; }; [2] Les pros nont pas peur dutiliser les pointeurs. Jai entendu : grce aux rfrences, en C++, on peut se passer des pointeurs, ouf ! . Une adresse, cest quand mme simple comprendre (29 avenue de la division Leclerc, cest trop compliqu comme notion ?). Dire que les pauvres Javasiens ne savent pas quils ne font rien dautre que de manipuler des pointeurs (amputs de surcrot et rebaptiss rfrences ).

68

Attributs objets (1)


Une classe peut avoir des attributs dune autre classe : [1]
class ClasseA { int a; public: ClasseA (int aa) { a = aa; std::cout << "\n ClasseA"; } }; class ClasseB { int b; ClasseA objetA; public: ClasseB () { b = 123; objetA = ClasseA(456); } };
Page 69

int main() { ClasseB bob; return 0; }

'ClasseA' : no appropriate default constructor available

Avant d'excuter quoi que ce soit dans le constructeur, les objets contenus sont construits automatiquement.

Notes : [1] Cest mme trs frquent, tous les exemples de la quasi-totalit des 60 planches prcdentes comportaient des exemples dattributs de ce genre. Que se passe t-il dans lexemple de la planche ? Une classe B essaie de dfinir un attribut appartenant la classe A. Au moment de la construction dun objet de la classe B, cest le constructeur par dfaut de A qui est appel, mais celui-ci nexiste pas, car le concepteur ne la pas crit. Il ny a pas moyen dappeler ainsi le bon constructeur de A, celui qui prend un entier en argument. Exemple : Exple_61_attributsObjets

69

Attributs objets (2)


Maintenant a marche :
class ClasseA { int a; public: ClasseA (int aa){ a = aa; std::cout << "\nClasseA"; } }; class ClasseB { int b; ClasseA objetA; public: ClasseB () : b(123), objetA(456) {} }; int main() { ClasseB bob; return 0; }

En conclusion : 1) quand un objet est attribut dun autre objet, son constructeur est excut avant que le corps du constructeur de la classe conteneur ne le soit [1] ; 2) si on n'utilise pas de liste d'initialisation, le code ne fonctionnera pas (risque d'appels implicites de constructeurs par dfaut ou par copie qui n'existent pas), ou sera inefficace (construction, puis copie).

Page 70

Notes : [1] Cf la planche prcdente intitule la vie dun objet . La seule solution : appeler le constructeur voulu dans la liste dinitialisation. Ainsi le compilateur sait quil na pas chercher un constructeur par dfaut qui nexiste pas. Exemple : Exple_61_attributsObjets

70

Tableaux dobjets
Quand on cre un tableau d'objets, un appel de constructeur est effectu pour la construction et l'initialisation de chaque lment individuel. Rien n'oblige ce que le mme constructeur soit appel pour tous les lments.
Fichier Point.h class Point { private: double x, y; int numero; public: Point(); Point(int n); Point(double xx, double yy); ~Point(); }; Fichier Main.cpp #include "Point.h" // Appels de constructeurs par dfaut : Point tab1[3]; Point tab2[3] = {Point(), Point(), Point()}; Point *tab3 = new Point[3]; // Appels htrognes : Point tab4[3] = {10, Point(1.0, 2.0), Point()};

Page 71

Notes : On utilise les tableaux dobjets frquemment, mais rarement la syntaxe qui permet dappeler divers constructeurs. Exemple : Exple_62_tableaux

71

Exercice
Qu'affiche le programme suivant ? Et pourquoi ? #include <iostream> class rectangle { double len; double wid; public: rectangle(double w) : wid(w), len(wid*2) { } double area() { return (len * wid); } }; void main() { rectangle x(10.0); std::cout << x.area() << std::endl; }

Page 72

Exercice : Exple_63_initialisation

72

Attributs de classe static (1)


Jusqu' prsent, nous avons considr que chaque objet-instance d'une classe disposait de son propre exemplaire des attributs dont chaque objet dispose. Mais il existe galement des donnes qui n'existent qu'en un seul exemplaire, et dont aucun objet ne possde une version personnelle : ces donnes sont des attributs de classe, on les spcifie par le mot-cl static. Exemples d'utilisation : connatre le nombre d'objets d'une classe : on crera une variable de classe qui s'incrmente dans chaque constructeur et diminue dans le destructeur ; connatre la taille mmoire occupe par les objets d'une classe : idem ; plus gnralement, donne commune tous les objets d'une classe.

Page 73

UML : Les attributs de classe sont prcds dun $ et/ou souligns.

73

Attributs de classe static (2)


Pour crer un attribut de classe : 1) le dclarer dans la dfinition de la classe (".h") avec le mot-cl static ; 2) le dfinir globalement en dehors de la classe (".cpp") sans le mot-cl static, mais en faisant prcder son nom de celui de la classe et (::).
Fichier Point.h
class Point { private: double x, y; int numero; static long MEMORY; public: static int NBR; Point(int n); ~Point(); };
Page 74

Fichier Point.cpp
long Point::MEMORY = 0; int Point::NBR = 0; Point::Point(int n) : numero(n), x(0.0), y(0.0) { NBR += 1; MEMORY += sizeof(Point); } Point::~Point() { NBR -= 1; MEMORY -= sizeof(Point); }

Notes : Les attributs static dune classe sont considrs par le programme comme des variables globales (au sens de uniques ). A ce titre, ils ne peuvent tre initialiss quune seule fois; cela ne peut-tre fait que dans un fichier qui est compil et non dans un fichier den-tte (.h). Exemple : Exple_64_attributsStatic

74

Attributs de classe static (3)


Les attributs de classe peuvent tre dclars publics, privs ou protgs. Pour accder un attribut de classe : pour un objet de la classe : accs libre, comme un attribut ordinaire ; de l'extrieur : l'accs doit tre public, on y accde soit par l'intermdiaire d'une instance, soit par le nom de la classe suivi de deux points (::).
Fichier Point.h class Point { private: double x, y; int numero; static long MEMORY; public: static int NBR; Point(int n); ~Point(); }; Fichier Main.cpp #include "Point.h" { Point p1(1); Point *p2 = new Point(2); ... = p1.MEMORY; ... = p1.NBR; ... = p2->NBR; ... = Point::MEMORY; ... = Point::NBR; } // Interdit, private // OUI // OUI // Interdit, private // OUI

Page 75

Notes : Les attributs de classe, peuvent servir dfinir des variables globales du programme, tout en les protgeant dans des classes (pour viter les conflits de noms). En C++, on verra plus loin que lutilisation des namespace a aussi cette fonctionnalit. Exemple : Exple_64_attributsStatic

75

Mthodes de classe static


Comme les attributs de classe, les mthodes de classe sont des fonctions qui peuvent tre appeles, sans le support dune instance. Autrement dit : elles ne connaissent pas le pointeur this; elles ne peuvent manipuler que les attributs de classe static . On les utilise beaucoup en Java (o tout doit tre dfini lintrieur dune classe), moins en C++, car il est possible dans ce langage de dfinir des fonctions la mode du langage C, sans notion oriente-objet. Par exemple la classe java.lang.Math dfinit toutes les fonctions mathmatiques usuelles.

Page 76

Notes : A mon avis, on ne devrait plus se servir du tout de fonctions la C classiques. Pour une fois, Java a raison dimposer cela.

76

Notation UML : diagrammes de classes (1)

Nom de la classe Nom de la classe attribut attribut : type attribut : type = valeur_initiale ... methode() methode() : type_retour methode(liste_args) mthode(liste_args) : type_retour ... # + / /# /+ $ #$ +$ + # +$ #$ $ attribut attribut attribut attribut attribut attribut attribut attribut attribut mthode mthode mthode mthode mthode mthode priv protg public driv priv driv protg driv public de classe priv de classe protg de classe public publique protge prive de classe publique de classe protge de classe prive

Page 77

Notes : La notion dattribut driv est une particularit propre UML. Il sagit dun attribut dont la valeur se dduit de celle des autres. Par exemple pour une liste, lattribut isEmpty est un boolen qui se dduit de ce que contient la liste, il vaut true si la liste est vide.

77

Notation UML : diagrammes de classes (2)


Associations
Classe 1 nbr nom de l'association nbr rle 2 Classe 2 nbr : reprsente la multiplicit 0..1 0..N 0..* 1..N 1..* : zro ou un : zro N : zro ou plus : un N : un ou plus 1 : exactement 1 N : exactement N N..M : de N M N..* : N ou plus {ordered}

rle 1

/ association drive association unidirectionnelle Classe 3

nom de l'association Classe 1 Classe 2

Agrgations/Compositions
agrgation unidirectionnelle Classe 1 Classe 2

Classe association attributs ... methodes ...

agrgation composite bidirectionnelle

Classe 3

Page 78

Notes : Nous avons vu la notion de composition. Nous allons voir les notions dassociation simple, dagrgation et de classe-association.

78

Associations entre classes (1)


Une relation (lien d'association) entre classes traduit une dpendance. On parle de relation "utilisation" (relation "use"). un objet point peut tre partag par plusieurs objets ; la destruction du "pointant" n'entrane pas la destruction du "point" ; il est interdit de dtruire le point s'il existe des objets en relation avec lui ; la copie du "pointant" n'entrane pas la copie du point.

Relation unidirectionnelle :
avion1 avion2 intercepteur1

instances UML
atmosphereStd76

Page 79

Explications : Toutes les instances de lexemple (les avions et lintercepteur) utilisent une mme instance de modle datmosphre. Ils ne possdent pas cette instance, il ne sagit donc pas l dune relation de composition comme celles que nous avons vu jusqu prsent.

79

Associations entre classes (2)


En C++, une relation dassociation de multiplicit 1 ou 0..1 se traduit par un pointeur [1].
class Atmosphere;

classes UML
Avion volue dans 1

[2]

Atmos_Std76 Intercepteur volue dans 1

class Avion { Atmosphere *atmos; ... }; class Intercepteur { Atmosphere *atmos; ... };

volue dans Mobile 1 Atmos_Std76

Avion

Intercepteur

Page 80

Notes : [1] ou ventuellement par une rfrence dans le cas dune multiplicit de 1. En aucun cas il ne peut sagir dun attribut-objet qui ne peut servir qu reprsenter une relation de composition. [2] Le premier diagramme de classes de la planche prsente ltat de la conception dans une version prliminaire, avant que lon gnralise les deux sous-classes dobjets mobiles en une super-classe nomme Mobile .

80

Associations entre classes (3)


Si la relation est bidirectionnelle et de multiplicit 1 ou 0..1, elle se traduit par un pointeur dans chacune des classes en relation. [1]
class Avion { Radar *cible; ... }; class Radar { Avion *objet_suivi; ... };

Avion

-objet_suivi 0..1

-cible 0..1

Radar

Si la multiplicit est suprieure 1, on utilisera des tableaux ou des listes de pointeurs. [2]
Avion -objets_suivis 0.. * Radar
class Radar { List<Avion*> objets_suivis; ... };

Page 81

Notes : [1] Le problme des relations bidirectionnelles, cest quil faut maintenir cohrente la bidirection : si on modifie un des cts, il faut modifier lautre en consquence. Cela est faire dans les mthodes (accesseurs / setters) qui agissent sur les attributs. [2] Les listes et les vecteurs dobjets exploitent la notion de templates que nous verrons plus loin. Il y a tout intrt aussi exploiter les possibilits de la librairie standard du C++ en matire de conteneurs (listes, piles, vecteurs, ).

81

Associations entre classes (4)


Un objet peut avoir une relation avec un objet du mme type :
class Avion { Avion *cible; ... };
-cible 0..1 Avion

Rcapitulation des exigences :


un objet point peut tre partag par plusieurs objets la destruction du "pointant" n'entrane pas la destruction du "point" il est interdit de dtruire le point s'il existe des objets en relation avec lui la copie du "pointant" n'entrane pas la copie du point
Page 82

OUI, avec l'utilisation de pointeurs C++ Faire attention dans le destructeur du pointant

Tenir jour un compteur des pointants Faire attention dans le constructeur de copie

Notes : Dans le respect des exigences, certaines sont plus faciles tenir que dautres. En particulier, celle qui consiste tenir jour un compteur des objets pointant vers linstance, nest pas facile mettre en place. Comme elle nest pas indispensable, elle nest gnralement pas implante.

82

Agrgations-Compositions (1)
Il y a peu de diffrence smantique entre la notion dagrgation et celle de composition que nous avons dj vue. Dans une composition, lobjet contenu na pas dexistence en dehors du conteneur. Dans une agrgation, lobjet contenu peut tre dtach et rattach un autre conteneur.
Avion 1 Navigat ion Intercepteur 1
Avion1 Avion2 Intercepteur1 Nav1 Nav2 Nav3

"Tous les avions et les intercepteurs disposent d'un moyen de navigation." A comparer lassociation : "Les mobiles voluent dans une atmosphre."

Avion

1 Atmos_Std76

Avion1 Avion2 Intercepteur1 AtmosphereStd76

Intercepteur

Page 83

Notes : Je ne vois pas trop lintrt de distinguer entre les relations dagrgation et de composition. Dans lexemple de la planche, les objets Navigation peuvent-ils vraiment tre donns quelquun dautre au cours de lexcution du programme ? En tout cas, formellement, une agrgation ne peut tre reprsente que par un pointeur (car on ne peut changer une rfrence ou un attribut-objet).

83

Agrgations-Compositions (2)
Rgles sur les agrgations : la destruction du propritaire entrane la destruction de l'agrgation ; il n'est pas possible de dtruire directement une agrgation, il faut le demander au propritaire ; la copie du propritaire entrane la copie de l'agrgation. En C++, une composition unidirectionnelle simple, de multiplicit gale 1 peut se traduire par un attribut-objet :
class Navigation; class Avion { Navigation ma_navigation; ... };

Mais cette mthode manque de souplesse et on prfrera utiliser ... des pointeurs.

Avion 1
Page 84

Navigation

Notes :

84

Agrgations (3)
Avec des pointeurs :
0..1 Avion 0..1 Navigation

class Navigation; class Avion { Navigation *ma_navigation; ... };

class Avion; class Navigation { Avion *mon_avion; ... };

Rcapitulation des exigences :


la destruction du propritaire entrane la destruction de l'agrgation il est interdit de dtruire l'agrgation, il faut le demander au propritaire la copie du propritaire entrane la copie de l'agrgation A faire dans le destructeur du propritaire

Tenir jour un indicateur d'appartenance A faire dans le constructeur de copie

Page 85

Notes :

85

Exercice facultatif
Cette exercice fait revoir les notions de passage par valeur dans les fonctions, de constructeur par dfaut et par copie, ainsi que la notion de vie dune instance : D'habitude, un constructeur par copie prend en argument une rfrence constante sur un objet de la classe : MaClasse (const MaClasse &c); Le constructeur par copie suivant est-il intressant ? MaClasse (MaClasse c); Si oui, expliquez ce qu'il apporte par rapport au constructeur par copie classique, si non, expliquez pourquoi.

Page 86

Exercice : Exple_67_copie

86

Fonctions amies (friend) (1)


Parfois, le principe de l'encapsulation des donnes devient un obstacle la rsolution d'une difficult et il est ncessaire de le contourner :
Fichier Point.h
class Point { double x, y; int numero; public: Point(); Point(int n); ~Point(); };

Supposons que l'on veuille crire une fonction de comparaison qui soit globale (hors de la classe) :
bool comparePoint(const Point& p1, const Point& p2) { if ((p1.numero == p2.numero) && (p1.x == p2.x) && (p1.y == p2.y)) return true; else return false; }

Le problme c'est que les donnes de la classe sont prives.

Page 87

Notes :

87

Fonctions amies (friend) (2)


La solution brutale consiste rendre publics tous les attributs de la classe Point, mais c'est plus qu'il n'en faut. Le mot rserv friend constitue une meilleure solution : il permet de signaler la classe qu'une fonction particulire aura tous les droits habituellement rservs aux mthodes de la classe.
Fichier Point.h
class Point { double x, y; int numero; public: Point(); Point(int n); ~Point();

ATTENTION ! Il s'agit bien d'une fonction globale (langage C), pas d'une mthode supplmentaire de la classe Point.

friend int comparePoint(const Point& p1, const Point& p2); };


Page 88

Notes : La fonction amie est dclare auprs de la classe Point . La fonction nest pas particulirement lie cette classe, il ny a donc aucune raison particulire pour que la dfinition (le corps) de la fonction se trouve dans les fichiers de la classe (Point.cpp). Mais rien ne lempche, bien sr.

88

Fonctions amies (friend) (3)


Les spcificateurs d'accs (priv/public) n'affectent pas les fonctions amies (ce sont des fonctions globales, forcment "publiques"). Il est possible aussi de dclarer amie une mthode d'une autre classe (faire prcder son nom du nom de cette classe et des deux points (::).
Fichier Point.h
class Point { ... friend void Segment::tracer(); ... };

Fichier Segment.h
class Segment { ... void tracer(); ... };

Exemples d'utilisation : fonctions de tests unitaires , classes en relations d'association ou d'agrgation , surcharges d'oprateurs , ...
Page 89

Chaque fois qu'on a besoin d'un accs privilgi une classe.

Notes : Les fonctions amies sont viter, autant que possible, puisquils sagit dexceptions la rgle de lencapsulation des donnes. Elles prennent par contre de limportance quand il sagit de redfinir des oprateurs, ce que nous verrons plus loin.

89

Classes amies (friend)


Une classe amie est une classe qui est autorise accder toutes les donnes et toutes les mthodes d'une classe. Une classe amie se dclare ou se dfinit indiffremment en partie prive ou en partie publique.
Fichier Point.h
class Point { double x, y; int numero; public: Point(); Point(int n); ~Point(); friend class Segment; };

Un objet Segment acquiert tous les droits qu'un objet Point aurait sur ses propres donnes/mthodes.

Page 90

Notes : Comme les fonctions amies, il vaut mieux viter autant que possible les classes amies. Personnellement, je men sers pour dclarer assez systmatiquement une classe de tests dans chaque classe dveloppe.

90