recap final Flashcards
Un contrat protège les deux parties
Protège le client (dans ce cas ci vous mêmes)
o
Spécifie quelles sont ses obligations
o
En retour, est assuré d’un certain résultat
Protège le fournisseur (sous contractant)
o
Spécifie le minimum requis (de la part du client):
le fournisseur ne peut être tenu responsable
d’avoir manqué à des engagements ne figurant
pas dans le contrat.
La spécification d’un contrat
Spécification d’une interface
peut être vue comme un contrat entre un client (l’utilisateur du
composant/classe) et un fournisseur (le composant/
Le contrat dit ce qui doit être rencontré par le client
pour pouvoir appeler une opération de l’interface :
précondition
Le contrat dit aussi ce qui doit être réalisé par le fournisseur
ce qui est garanti au client
pour rencontrer ce qui est prévu par l’opération
postcondition
Les assertions : le contrat du logiciel
Mécanismes pour exprimer ces conditions :
assertions
préconditions
postconditions :
assertions s’appliquant à des méthodes en particulier,
invariants de classe :
assertions s’appliquant à toutes les méthodes d’une classe en
tout temps.
Une spécification plus complète d’une
opération offerte par un composant
deviendrait:
le nom de l’opération
o
le nombre, le type et l’ordre des paramètres
o
les préconditions
o
les postconditions
o
le type de retour.
Invariant de classe
Autre type d’assertion
o
représente l’ensemble des conditions logiques devant
être respectées pour assurer un comportement correct
d’une classe.
Immédiatement après la création d’un objet de
cette classe,
l’invariant doit être respecté et préservé tout au
long de la vie de l’objet.
Les MACROs pour le contrat
“fonction” définie par un #
Remplacement textuel, fait par le
préprocesseur.
Dans le fichier ContratException.h ,
1.
Définition de ces classes
2.
2.+ définition des MACROs suivantes:
PRECONDITION(test);
POSTCONDITION(test);
ASSERTION(test);
INVARIANT(test);
INVARIANTS();
Regardons ContratException.h
mise en oeuvre test unitaire
Doit être structuré
Doit être répétable
i.e. on doit pouvoir le faire exécuter le plus
souvent possible.
Doit fournir un rapport d’exécution extrêmement
simple (ok, pas
résultat d’une assertion
success (test réussi),
nonfatal failure (test
fatal failure (test échoué et arrête la
Construction et destruction :
Ordre d’appel
Construction des objets de la hiérarchie
o
de la classe de base tout en haut jusqu’à la
classe dérivée
Destruction des objets de la hiérarchie
o
de la classe dérivée jusqu’à la classe de base
Visibilités :
o
Privée : Accès interne de la classe.
o
Publique : Accès à tous les utilisateurs
o
Protégée : Accès aux héritiers
Les méthodes d’une classe ont
toujours accès aux attributs de la
classe, peu importe la visibilité
les données privées ne sont manipulables que par les méthodes
de la classe à laquelle les données appartiennent.
L’héritage ne donne pas d’accès privilégié pour la visibilité privée
Ajout de méthodes
Triangle qui est une classe dérivée de Polygone (
o
a immédiatement accès à cette nouvelle fonctionnalité,
Triangle2 qui utilise Polygone (
o
doit être ajoutée manuellement dans la classe Triangle2
Résultat intéressant d’un point de vue de gestion du code.
tout héritier de la classe Polygone a accès à ses méthodes
qu’elles soient écrites maintenant ou dans le futur
Remplacer, hériter, augmenter …
Une classe dérivée D peut décider de
prendre action sur une méthode m() de la
classe de base B:
La classe dérivée remplace la méthode
B::m() par D::m() en implantant un
algorithme différent.
La classe dérivée hérite de B::m() sans
changement.
La classe dérivée augmente la méthode
B::m() par une méthode D::m() qui appelle
d’abord B::m() avant de faire d’autre tâches.
En C++, trois formes :
Polymorphisme ad hoc :
Surcharge de m é thode(d é j à vu)
o
Polymorphisme param é trisable
Les templates
o
Polymorphisme pur
Le polymorphisme pur
Mé thodes virtuelles , alli é es à l’h é ritage:
o
permet de rendre les programmes extensibles par l’h é ritage
de comportements existants
ajout de comportements sp é cifiques au besoin.
Traitement d une famille de classe s une hi é rarchie de
fa ç on g é n é rique .
o
On n’a pas à identifier le type de la classe avec un switch
comme dans les langages non OO.
Traitement g é n é rique à partir de la classe de base
m
é thodes virtuelles .
o
à l’ é chelle d’une hi é rarchie de classes.
Signature des m
é thodes virtuelles
Une fonction virtuelle doit avoir la même signature
et même type de retour dans toutes la hi é rarchie.
Une fois qu’une fonction a é t é d é clar é e virtuelle,
elle le demeure dans toute la hi é rarchie à partir de
ce point
Méthodes virtuelles
Seule une fonction membre peut être virtuelle
Un constructeur ne peut être virtuel
Un destructeur peut être virtuel
Classes abstraites ou concr
è tes
En g é n é ral :
o
Cr é ation d une classe => cr é er des instances
Ce n’est pas toujours le cas…
Si cr é ation d une classe abstraite ,
Pas de cr é ation d’instance de cette classe.
Exemple :
on peut se servir d’une telle classe pour regrouper des concepts sous
une classe th é orique .
Bien plus que la th é orie
imposer une interface g é n é rale que toutes les classes h é riti è res
devront r é implanter
En C++, ¸ pour cr é er une classe purement abstraite
au moins une de ses m é thodes d é clar é es purement virtuelle.
trois grandes zones de mémoire:
Zone de la pile d’appel
*
Zone d’adressage statique
*
Zone d’allocation dynamique sur le monceau
*
Zone d’allocation dynamique
Les deux premières zones ont leur utilité
o
demeurent insuffisantes pour la plupart des
programmes sérieux.
dans un programme, on ne peut
o
estimer la quantité de mémoire nécessaire
o
prévoir à quel moment celle ci sera nécessaire.
o
réserver une très grande partie de la mémoire
simplement parce qu’on prévoit en avoir besoin.
utiliser l’allocation dynamique pour obtenir
et libérer de la mémoire lorsqu’on en a
vraiment besoin.
pour allouer de la mémoire dynamiquement,
opérateur new
On doit absolument récupérer l’espace alloué par le new
sinon on laisse ce qu’on appelle des déchets ( memory leaks
opérateur delete
On récupère l’espace occupé par un objet sur le monceau
o
Appel de l’opérateur delete sur le pointeur obtenu à partir d’un
new
Fuite de mémoire
1 new 1 delete
Qui a la responsabilité de libérer?
Solution : les pointeurs intelligents
unique_ptr
shared_ptr
weak_ptr
unique_ptr
Un seul emplacement mémoire référencé par un seul
pointeur
o
un unique_ptr est propriétaire de l’emplacement pointé
shared_ptr
Un même emplacement référencé par plusieurs pointeurs
o
Compteur de référence (Lorsque le dernier shared_ptr est
détruit, l’objet pointe est également détruit.)
o
Pas de notion de propriété
weak_ptr
un weak pointer permet de pointer
un objet géré par un shared pointer
sans impacter son compteur de
références
(solution aux références circulaires
deux sortes de copie:
La copie de surface (ou shallow
o
2. La copie en profondeur (ou deep
Si on
Si on ne fait rien de particulier,
le langage C++ fait toujours une copie de
surface lors de
la copie d’un objet.
Si on désire une copie en
profondeur
il faut l’implanter.
Forme canonique de Coplien
Pour toute classe qui contient des allocations
dynamique de la mémoire liées à ses attributs
(notion de profondeur)
o
Utiliser des pointeurs intelligents
o
Implanter les méthodes :
constructeur de copie
surcharge de operator
Lancer une exception
Le mécanisme des exceptions :
o
lancer des exceptions sur le site de l’erreur.
o
transférer le contrôle à une autre partie du code
gérer la situation avec compétence.
spécifiés à l’aide de blocs
try catch
try
// code pouvant lancer une exception
//avec
throw Type exception
catch (Type exception erreur
// erreur contient de l’information
sur
//
// code de gestion de l’exception
Hiérarchie d’exceptions
Du côté logic_error i.e. erreur de programmation.
o
Du côté runtime_error par contre, il s’agit d’exception pouvant
toujours se produire.
o
La théorie du contrat : exceptions attachées à cette hiérarchie
Si on veut gérer toutes les exceptions de contrat,
o
mentionner
catch (ContratException& e)
o
toutes les exceptions de contrat : precondition, postcondition,
invariant et assertion seront attrapées.
Si on veut gérer seulement les préconditions,
mentionner :
catch (PreconditionException &e)
On pourrait gérer toutes les erreurs de programmation en
mentionnant :
catch (logic_error& e)
Attraper toutes les exceptions et relancer
pour faire une action protectrice
pour faire un nettoyage quelconque.
try
{ // code
catch (…)
{ // Gestion de n’importe quelle exception
throw ; // Relance l’exception
Framework : définitions
pour faciliter le développement d’applications
dans un contexte déterminé.
ensemble de classes qui coopèrent et
permettent des conceptions réutilisables dans
des catégories spécifiques de logiciels.
utilisation sous classage (héritage et
polymorphisme) de classes abstraites.
framework : très proche d’une librairie de classes
: très proche d’une librairie de classes
tous les deux des composants réutilisables codés.
bibliothèque de classes = ensemble de composants,
o
classes pouvant être réutilisées
mécanisme d’agrégation et d’héritage.
frameworks = librairies de classes +
o
relations,
o
interactions entre des instances de classes.
Mécanisme d’instanciation
Processus pour obtenir une classe utilisable à partir d’une template
: instanciation de la template
template ————–> classe —————-> objet
Les méthodes : Notes supplémentaires
Les méthodes ne sont plus dans un fichier cpp
mais dans le .h après la déclaration de la
classe ou dans un hpp inclut par le .h
Classes patron
patron de classe utilisé avec de nouveaux
arguments nouvelle classe patron compilée.
déclaration d’un objet de type
std vector int > et d’un autre de type
std vector <double>
Instanciation de deux classes différentes.
Les objets seront de types différents,
Aucun lien entre les deux (pas même une
conversion).</double>
Fonctions patron
comportement similaire avec les fonctions
:
chaque appel d’un patron de fonction avec de
nouveaux types d’arguments compile une nouvelle
fonction patron.
Composantes principales de STL:
Algorithmes : définir des procédures de
traitement.
Conteneurs : gérer un ensemble d’espaces
mémoire selon les structures de données
Itérateurs : procurer à un algorithme une façon
de traverser un conteneur.
Comme avec les pointeurs sur un vecteur C++, l’itérateur
peut être incrémenté ou décrémenté pour parcourir le
peut être incrémenté ou décrémenté pour parcourir le
conteneur ( iter ou iter
Lorsqu’on spécifie un intervalle avec deux itérateurs , iter1
et iter2 , il est nécessaire que iter2 soit accessible à partir
de
iter1 , i.e. un nombre fini de ++iter1 pour atteindre
iter2
Les propriétés des itérateurs dépendent des conteneurs
qui
les fournissent
Hiérarchie des itérateurs
aléatoire
bidirectionel
unidirectionel avant
entrée(lire)/sortie(écrire)
séquence
vector deque list
association
set multiset map multimap
adaptaeur
stack queue priority queuev
Comment accéder les valeurs?
Si l’accès aléatoire est important
vector ou deque
Si l’accès séquentiel est suffisant
un des autres conteneurs peut être adapté.
Les algorithmes génériques
Les algorithmes fournis avec STL sont découplés du
conteneur sur lequel ils agissent
o
utilisation des itérateurs.
Tous les conteneurs dans la même catégorie peuvent
utiliser les mêmes algorithmes.
+/-
+ librairie majeure, performance, extensible
o
connaître et comprendre les exigences et les limites