Title: 5ime Classe Mercredi, 19 octobre Prog CSI2572
15ième Classe (Mercredi, 19 octobre)Prog CSI2572
2La semaine dernière
La programmation orientée objet cherche à
modéliser informatiquement des éléments du monde
réel en entités informatiques appelées objets.
Les objets sont des données informatiques
regroupant les principales caractéristiques des
éléments du monde réel (taille, couleur, ...).
La difficulté du processus de modélisation est
dans la création d'une représentation abstraite
d'entités ayant une existence matérielle (chien,
voiture, ampoule, ...) ou bien virtuelle
(sécurité sociale, temps, ...).
3La semaine dernière
Dans le monde réél, deux T-shirts peuvent être
identique et distincts. La classe , c'est la
structure d'un objet, c'est-à-dire la déclaration
de l'ensemble des entités qui composeront un
objet. Une classe peut être considérée comme un
moule à partir duquel on peut créer des objets.
Un objet est donc "issu" d'une classe. C'est
une instanciation d'une classe, c'est la raison
pour laquelle on pourra parler indifféremment
d'objet ou d'instance.
4La semaine dernière
- Une classe est composée de deux parties
- Les attributs (parfois appelés données membres)
il s'agit des données représentant l'état de
l'objet - Les méthodes (parfois appelées fonctions
membres) il s'agit des opérations applicables
aux objets - Si on définit la classe voiture, les objets
Toyota_Civic, Mustang2003 seront des
instanciations de cette classe. Il pourra
éventuellement exister plusieurs objets
Toyota_Civic, différenciés par leur numéro de
série. - Deux instanciations de classes pourront même
avoir tous leurs attributs égaux sans pour autant
être le même objet.
5La semaine dernière
Dans ce modèle, un véhicule est représenté par
une chaîne de caractères (sa marque) et trois
entiers la puissance fiscale, la vitesse
maximale et la vitesse courante.
chaque objet véhicule aura sa propre copie de ses
données on parle alors d'attribut d'instance.
L'opération d'instanciation qui permet de créer
un objet à partir d'une classe consiste
précisément à fournir des valeurs particulières
pour chacun des attributs d'instance.
6La semaine dernière
- La déclaration de la classe commence par le mot
clef class et est encadrée par une paire
d'accolades. L'accolade finale est suivie d'un
point virgule. Les membres déclarés après le mot
clef public forment l'interface de la classe.
Ceux qui suivent le mot private sont invisibles
de l'utilisateur - L'ordre de déclaration des méthodes et des
attributs est laissé au libre arbitre du
programmeur. - La déclaration des attributs est semblable à la
déclaration d'une variable. Celle d'une méthode
au prototype dune fonction.
7La semaine dernière
- Lors de l'implémentation des méthodes, il est
nécessaire de préfixer le nom de la méthode
implémentée du nom de la classe suivi de ''.
Par exemple, l'implémentation de la méthode
deplacerVers de la classe Point se fait en
spécifiant - PointdeplacerVers
8(No Transcript)
9- Encapsulation, polymorphism 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. - Polymorphism
- 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
10Encapsulation I
- 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 lutilisateur, linterface 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 (cest-à-dire en fait du client de
lobjet), 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é lintervention de
plusieurs méthodes ou même la création dobjets
temporaires etc.
11Encapsulation II
- En C, on choisit le paramètres d'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é.
12class Avion public // fonctions membres
publiques void init(char , char , float)
void affiche() private // membres
privées char immatriculation6, type
float poids // fonction membre
privée void erreur(char message) //
n'oubliez pas ce après l'accolade
13La semaine dernière
- Les fonctions membres sont définies dans un
module séparé ou plus loin dans le code source. - Syntaxe de la définition hors de la classe d'une
méthode - type Classenom_méthode( paramètres_formels )
- // corps de la fonction
-
14 void Avioninit(char m, char t, float p)
if ( strlen(m) ! 5 ) erreur("Immatriculati
on invalide") strcpy( immatriculation,
"?????") else strcpy(immatriculation,
m) type new char strlen(t)1
strcpy(type, t) poids p void
Avionaffiche() cout ltlt immatriculation ltlt
" " ltlt type cout ltlt " " ltlt poids ltlt endl
class Avion public // fonctions membres
publiques void init(char , char , float)
void affiche() private // membres
privées char immatriculation6, type
float poids // fonction membre
privée void erreur(char message) //
n'oubliez pas ce après l'accolade
15Comme pour struct , le nom de la classe
représente un nouveau type de donnée. On peut
donc définir des variables de ce nouveau type
(créer des objets ou des instances)
Avion av1 // une instance simple (statique)
Avion av2 // un pointeur (non initialisé)
Avion compagnie10 // un tableau d'instances
av2 new Avion // création (dynamique) d'une
instance
16Après avoir créé une instance (de façon statique
ou dynamique) on peut accéder aux attributs et
méthodes de la classe. Cet accès se fait comme
pour les structures à l'aide de l'opérateur . ou
-gt.
av1.init("FGBCD", "TB20", 1.47)
av2-gtinit("FGDEF", "ATR 42", 80.0)
compagnie0.init("FEFGH","A320",
150.0) av1.affiche() av2-gtaffiche()
compagnie0.affiche() av1.poids 0 //
erreur, poids est un membre privé
17Le constructeur I
- Le constructeur est une méthode qui porte le
même nom que la classe. Cest dans le
constructeur que les attributs dun objet sont
initialisées lors de sa création. - Un constructeur ne peut pas spécifier de valeur
ou type de retour. - Le constructeur dune classe est éxécuté
automatiquement à chaque fois quune instance de
la classe est crée. Que se passe t il si
linstance est passée par valeur comme paramètre
à une fonction? - Une classe peut avoir ou non un constructeur par
défaut. Il sagit dun constructeur sans aucun
paramètre.
18- Si aucun constructeur na été défini dans la
classe, C en crée un automatiquement. Cest un
constructeur par défaut, et il ne fait rien. Une
classe a donc toujours un constructeur, mais pas
forcément un constructeur par défaut en effet,
si on ne définit que des constructeurs qui
prennent des paramètres, C ne fournit pas le
constructeur par défaut automatiquement. - Lorsquun constructeur par défaut nexiste pas,
on ne peut déclarer une instance de classe sans
préciser de paramètres. - Par exemple, pour lexemple suivant, lappel
- autre a
- est illégal.
Le constructeur II
class autre double d public
autre(double dd) d dd
19Le constructeur III
- Si on veut créer un tableau dinstances de la
classe sans donner de valeurs initiales, il faut
définir un constructeur par défaut. Il est alors
appelé pour tous les éléments du tableau - Avion A10
- //10 appels du constructeur par défaut de Avion
- important bien que les constructeurs aussi
peuvent avoir des arguments par défaut comme
toute autre fonction - autre a // ok
- autre tab3
- //NON, car pas de constructeur par défaut
class autre double d public
autre(double dd 0) d dd
20Le constructeur IV
- Un appel à l opérateur new (création d une
instance de manière dynamique) provoquera un
appel de constructeur. - Plane C new Plane(...)
21Le constructeur VI
class show private int a public
show(int) int get_a()return
a showshow(int i) a i coutltlt
"Appel du constructeur show(int i)" int
foo(show a) coutltlt"Dans foo"ltltendl
return a.get_a() int main()
foo(1) return 1
- Le compilateur gère lui-même les initialisations
de variables automatiques. Les arguments de
fonction sont des variables automatiques. Elles
sont donc elles aussi gérées par le compilateur. - C'est la raison pour laquelle l'exemple suivant
est valide
22Le constructeur V
- De la même manière, l'appel suivant serait
parfaitement légitime - foo( show(1) )
- Dans ces cas les constructeurs adéquats sont
appelés à lentrée de la fonction (et les
destructeurs à la sortie). - Un constructeur ne peut pas être appelé autrement
que lors dune initialisation. Cependant, il peut
lêtre de différentes façons. Par exemple, sil
existe un constructeur qui nadmet quun seul
paramètre, ou plusieurs mais tel que tous les
arguments sauf le premier ont une valeur par
défaut, on peut lappeler en écrivant le signe
égal suivi du paramètre - autre au 1.2
- // appel de autreautre(1.2)
23Le constructeur VI
- Cette écriture est équivalente à la forme
classique - autre au(1.2)
- En outre, il est possible dinitialiser des
tableaux de cette façon - autre atab4 1.2, 2, 0.7, -9.9
- Par contre, dans ce cas, il faut absolument
préciser toutes les valeurs initiales parce que
il n'y a pas de constructeur par défaut dans
notre implémentation de la classe autre. -
24Le constructeur VI
- Il est parfaitement possible de préciser une
valeur par défaut à un argument de type classe,
pourvu quon utilise un constructeur - void f(exemple ex exemple() )
- void f2(exemple ex exemple(1, 1) )
- void g(autre au 0)
- Dans le dernier cas, on a encore utilisé le
changement de type automatique.
25Le constructeur VII
- Il y a un type spécial de constructeur le
constructeur par copie - Si un constructeur par copie est spécifié, il
sera appelé à chaque fois quun objet est rendu
par une fonction, et à chaque fois quun objet
est passé par valeur à une fonction. - Cest grâce au constructeur par copie que le
programmeur évite un certain nombre de problèmes
dallocation de mémoire lorsque celle ci est
référée par des variables membres de lobjet.
26- class classexmpl
- // champs ...
- public
-
- classexmpl()
- // constructeur par défaut
-
- classexmpl(int i)
- // un autre constructeur
-
- classexmpl(classexmpl c)
- // constructeur de copie
- // méthodes...
-
- classexmpl c1
- // constructeur par défaut
- classexmpl c2 c1
Le constructeur VIII
- Les constructeurs dune classe donnée classe
peuvent avoir nimporte quoi comme arguments,
sauf des données de type classe. Ils peuvent
avoir des pointeurs classe comme arguments,
ainsi que des références classe. Cependant, dans
ce dernier cas, le constructeur ne doit avoir
quun seul argument classe, et les autres
arguments, sil y en a, doivent avoir une valeur
par défaut. - Ce constructeur est alors appelé constructeur de
copie. Il sert lors daffectations du genre
27Le constructeur par copie
- Toute classe a nécessairement un constructeur de
copie. Lorsquaucun nest défini explicitement,
le compilateur en crée un automatiquement, qui se
contente de recopier champ par champ largument
dans this. - Le constructeur de copie nest appelé (comme
tout constructeur) que lors dune initialisation.
Donc, si on écrit - c2 c1
- Ce nest pas le constructeur qui est appelé,
mais lopérateur daffectation , qui par défaut
recopie les champs un à un il faut donc
également le redéfinir.
28Le constructeur par copie
- Cette remarque met en relief un fait essentiel
qui est que lors des deux écritures - exemple c2 c1 // appel du constructeur de
copie - c2 c1 // appel de l'opérateur d'affectation
- Lopérateur daffectation nest appelé quune
fois (la seconde), tandis que cest le
constructeur de copie qui est appelé la première
fois. Par défaut les deux appels provoquent le
même effet Ce qui n'est pas le cas dans des
classes définies par un programmeur.
29class Obj private int a public Obj()
Obj() ObjObj() printf("\n --gt In
ObjObj()\n") a new int10 for(int i0
ilt10i)aii ObjObj() printf("\n
--gt In ObjObj()\n") delete a a
(int)0 void foo(Obj Inst) printf("\n --gt
In foo(Obj)\n")
Le constructeur par copie sert à
Que ce passe t'il si on ne définit pas de
constructeur par copie ?
30Le constructeur par copie sert à
Maintenant int main() Obj
test foo(test)
Dans foo(obj)
Copy de test
a
test
a
Allocation mémoire du tableau
31 int main() Obj test foo(test)
Dans foo(obj)
Copy de test
test
a
a
Allocation mémoire du tableau de l'objet d'origine
Allocation mémoire de la copie de l'objet
d'origine
Où les deux tableaux sont égals, valeurs par
valeurs.
32La déclaration ressemble à
class Obj private int a public Obj()
Obj(const Obj) Obj() ObjObj(const
Obj cpy) a new int10 for(int i0
ilt10i) aicpyi
33Le destructeur
- Le destructeur est une méthode particulière qui
porte le même nom que la classe précédé du symbol
. Le destructeur est la dernière methode
appelée par une instance lorque le bloc de code
dans laquelle celle ci évoluait a terminé son
exécution. - Le destructeur est aussi appelé lors d un appel
d opérateur delete sur l instance. - Cest dans le destructeur que la mémoire qui
avait été allouée à la construction et pendant la
vie de l instance est rendue au système. - Que se passe t il si deux blocs mémoires sont
partagé par deux instances de la même classe?
34Le destructeur II
- Un destructeur na aucun résultat, comme les
constructeurs, et nadmet aucun argument de ce
fait, il ne peut y avoir quun destructeur par
classe. - Dune façon générale, le destructeur doit tout
remettre en ordre dans ce que linstance de
classe peut avoir modifié. Outre la libération de
la mémoire prise, il peut aussi avoir à fermer
des fichiers ouverts, à détruire des éléments
provisoires, etc. - Le destructeur standard (fournit par défaut) ne
fait rien.
35new et delete avec constructeurs et destructeurs
- Lopérateur new réserve la place mémoire
nécessaire à lobjet dans le heap il appelle
aussi un constructeur. Inversement, delete
appelle dabord le destructeur, puis libère la
place mémoire. - Comme une classe peut avoir plusieurs
constructeurs, on peut préciser quel constructeur
est appelé au moment de lappel de new. Il suffit
pour cela décrire la liste des arguments
derrière le nom de classe qui suit new. - exemple pe1 new exemple(1, 2)
- // appel du constructeur 2
- exemple pe2 new exemple
- // appel du constructeur 1
- classexmpl c2 new classexmpl(c1)
- // constructeur de copie
36new et delete avec constructeurs et destructeurs
- Lorsquaucun paramètre nest précisé le
constructeur par défaut est appelé sil
nexiste pas, une erreur de compilation se
produit. - Il est possible de créer un tableau avec new,
mais dans ce cas cest le constructeur par défaut
qui est obligatoirement appelé il ny a pas de
moyen den préciser un autre (contrairement aux
tableaux statiques qui peuvent être initialisés
par un constructeur à argument unique). - Pour ce qui est de linstruction delete, il ny a
pas le choix - chaque classe ayant un seul destructeur
(possiblement implicite), cest celui-là qui est
appelé avant de supprimer la place mémoire.
37new et delete avec constructeurs et destructeurs
- Problème particulier aux tableaux
- exemple pex new exemple10
- ...
- delete pex // incorrect
- Le compilateur, qui na aucun moyen de connaître
la taille du tableau pointé par pex, nappellera
le destructeur que pour le premier élément, ce
qui peut poser problème. Pour lui demander de
tout détruire, il faut préciser explicitement
avec delete, le nombre déléments à supprimer - exemple pex new exemple10
- ...
- delete10 pex
- Il faut se rappeler de ceci dans la déclaration
du destructeur.
38L'opérateur d'assignement ()
student studentoperator(const student s)
if (s this) return this delete
name name new charstrlen(s.name) 1
strcpy(name,s.name) return this
- Lopérateur dassignement sert à assigner la
valeur dun objet à un autre objet. Quelle est la
différence entre lopérateur dassignement et le
constructeur par copie? - Lopérateur dassignement est souvent surchargé.
Comme pour le constructeur par copie, il faut
faire attention à la manière dont les variables
membres sont copiées lorsquelles référent une
adresse mémoire. - class student
- private
- char name
- int stno
- ...
- public
- student operator(const student) ...
-