132
1 Polytech Marseille , Prog. o. o. 1 Introduction à la Programmation Orientée Objet Marc DANIEL Ecole Polytech Marseille, Campus de Luminy, case 925, 13288 Marseille cedex 9 [email protected] Mars 2018 Polytech Marseille , Prog. o. o. 2 Plan Les concepts de la programmation orientée objet 4 un peu d’histoire 5 de la nécessité de langages adaptés 7 vers les langages objets 11 les principes généraux 13 la notion de classe 16 quelques langages 18 De C à C++ 19 Les concepts des langages de classes ; implémentation en C++ 55 les classes et les objets 56 les opérateurs 90 l’héritage 104 La généricité et les modèles 164 La gestion des exceptions 175

Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

Embed Size (px)

Citation preview

Page 1: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

1

Polytech Marseille , Prog. o. o. 1

Introduction à la Programmation Orientée

Objet

Marc DANIEL

Ecole Polytech Marseille, Campus de Luminy, case 925, 13288 Marseille cedex 9

[email protected]

Mars 2018

Polytech Marseille , Prog. o. o. 2

Plan

•  Les concepts de la programmation orientée objet 4 –  un peu d’histoire 5 –  de la nécessité de langages adaptés 7 –  vers les langages objets 11 –  les principes généraux 13 –  la notion de classe 16 –  quelques langages 18

•  De C à C++ 19

•  Les concepts des langages de classes ; implémentation en C++ 55 –  les classes et les objets 56 –  les opérateurs 90

–  l’héritage 104

•  La généricité et les modèles 164

•  La gestion des exceptions 175

Page 2: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

2

Polytech Marseille , Prog. o. o. 3

Plan (suite)

•  Quelques compléments 197 –  La norme C++ 198 –  Les espaces de noms 199 –  Amitié, Héritage et Généricité 205

•  Les composants prédéfinis 207 –  Les flux d’E/S 210 –  La classe String 216 –  Les conteneurs 221 –  Les itérateurs 230 –  Les algorithmes 234 –  Les traitements numériques 235

•  Au sujet de C++11 norme 2011 236 •  Conclusion sur C++ 251 •  Glossaire partiel 255

•  Bibliographie succincte 258 •  annexes 259

Polytech Marseille , Prog. o. o. 4

Les concepts de la programmation orientée objet

Page 3: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

3

Polytech Marseille , Prog. o. o. 5

Introduction / histoire

•  La préhistoire : –  les années 60 et les débuts de la programmation et des langages

•  Les années 70-80 : La programmation structurée –  analyse descendante

⇒  décomposition suivant les traitements ⇒  les logiciels sont organisés autour des actions qui traitent les objets

–  séparation traitement et données –  interdépendance des données à l’intérieur des traitements –  difficile à maintenir

⇒  Programme = Algorithmes + données

Polytech Marseille , Prog. o. o. 6

Introduction / histoire

•  La programmation et la conception orientée objet Ou un besoin de qualité

–  depuis 1975 –  essor dans les années 85 (C++, Eiffel) –  la consécration à partir des années 90

« La conception objet repose sur une idée apparemment élémentaire. Les systèmes informatiques réalisent certaines

actions sur certains objets. Pour obtenir des systèmes souples et réutilisables, il faut mieux structurer le logiciel

autour des objets que des actions »

Bertrand Meyer (concepteur d’Eiffel)

Page 4: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

4

Polytech Marseille , Prog. o. o. 7

•  Objectifs principaux (Génie Logiciel) :

–  réutiliser ce qui a déjà été écrit •  directement (le code, les modèles) •  adaptation (l’héritage)

–  augmenter la qualité

•  rapidité de la conception •  facilité de maintenance

•  ergonomie d’utilisation •  fonctionnement simple et efficace

Intro. / langages adaptés

développement

utilisation

Polytech Marseille , Prog. o. o. 8

•  Le logiciel doit être : •  valide •  robuste •  Modifiable (extensible) •  réutilisable •  Portable •  ergonomique •  efficace

•  La maintenance doit être facile •  évolution du logiciel (an 2000, Euro, …. !!!), vos futurs stages !! •  correction d’erreurs

⇒  Le logiciel doit nécessairement être modulaire •  et … les modules doivent être indépendants

Intro. / langages adaptés

Page 5: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

5

Polytech Marseille , Prog. o. o. 9

•  Dans une application, les coûts les plus importants proviennent :

•  De la programmation •  De la maintenance

–  Modification des spécifications par le client –  Non respect des spécifications –  Tests mal ou pas réalisés –  Bugs inévitables –  Adaptation à de nouveaux environnements –  …

•  Pour la rapidité •  Étude de la complexité •  Loi de Moore (1965)

Intro. / langages adaptés

Polytech Marseille , Prog. o. o. 10

•  Critères de modularité : –  Décomposition modulaire

•  la méthode permet de décomposer un problème en sous-problèmes dont les solutions peuvent être recherchées séparément

–  Composabilité modulaire •  la méthode fournit des éléments (modules) qui peuvent être combinés pour

traiter de nouveaux problèmes

–  Compréhensibilité modulaire •  la méthode produit des modules compréhensibles isolément

–  Continuité modulaire •  une petite modification de la spécification n’amène des modifications que

sur un ou quelques modules. Il ne doit pas y avoir d’impact sur l’architecture du système

–  Protection modulaire •  pas de propagation de l’effet d’une condition anormale

Critères proposés par Bertrand Meyer (voir bibliographie)

Intro. / langages adaptés

Page 6: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

6

Polytech Marseille , Prog. o. o. 11

Une « société » de modules respectant les critères de modularité

•  module : unité syntaxique du langage

•  un module doit communiquer avec peu de modules

•  les échanges entre modules doivent être le plus réduits possibles

•  les échanges entre les modules sont clairement explicités dans la définition des modules

•  toute information concernant un module est privée, sauf si elle est explicitement déclarée publique (masquage de l’information)

Intro. / vers les objets

Polytech Marseille , Prog. o. o. 12

les modules que l’on appellera objets

•  parlent peu

•  leurs conversations tiennent en quelques mots

•  leurs échanges sont publics, codifiés, donc à haute voix

•  la plupart des informations et des traitements sont privés

Intro. / vers les objets

Page 7: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

7

Polytech Marseille , Prog. o. o. 13

première vision des objets (modules)

•  décomposition en modules sur la base de leurs structures de données

•  un module est décrit comme une implémentation de types abstraits de données et des traitements associés

•  tout type est un module et vise versa –  y compris les types prédéfinis (int, float, …) –  Une structure au sens du C est un module sans traitement : ce n’est

pas la logique de l’orienté objet

•  chaque module a une interface qui définit comment il dialogue avec les autres –  Ce qui est public –  Ce qui est privé

Intro. / principes généraux

Polytech Marseille , Prog. o. o. 14

Programmation orientée objet

•  On s’intéresse aux objets avant de s’intéresser aux traitements –  le programme de plus haut niveau sera étudié le plus tard possible

•  La p.o.o relève de la création d’objets et de l’exécution d’envois de messages entre les objets

Quels sont les objets ? (il faut définir les bons objets) Quels traitement doivent-ils subir ? Quels liens ont les objets entre eux ?

•  Plusieurs points de vue possibles : Le plus « important » est l’utilisation de classes ou langages de classes

Intro. / principes généraux

Page 8: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

8

Polytech Marseille , Prog. o. o. 15

La classe : un moule

•  une classe correspond à –  une structure de données abstraites

•  partie structurelle composée de champs (appelés attributs ou membres)

–  des traitements à effectuer sur ces structures (appelés méthodes ou fonctions membres)

deux méthodes importantes : créateur et destructeur •  services disponibles sur la structure (partie opérationnelle) •  les propriétés de ces services

–  une interface (clairement identifiée) qui définit •  partie publique (ce que voit le client) •  les services accessibles auxquels on peut faire appel •  les variables visibles de l’extérieur (en nombre très réduit)

•  La façon dont les traitements sont réalisés ne regardent pas le monde extérieur

•  on peut modifier les attributs et les méthodes sans modifier l’interface

Intro. / la notion de classe

Polytech Marseille , Prog. o. o. 16

•  Les classes sont reliées entre elles par des relations d’héritage –  on réutilise –  on spécialise

•  différentier les traitements •  préciser les attributs

•  Les objets sont définis à partir des classes par moulage –  instanciation par moulage –  la classe sert de modèle, de moule

•  On ne communique avec l’objet qu’en invoquant une des méthodes de son interface

•  On a une encapsulation des données et des traitements qui permet l’abstraction des données

•  (voir glossaire)

Intro. / la notion de classe

Page 9: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

9

Polytech Marseille , Prog. o. o. 17

Une classe très incomplète

class Triangle { Point _p1, _p2, _p3 ; // données privées public : ... float aire (…) ; float perimetre (...) ; } ;

•  En dehors de la classe, on peut calculer l’aire, le périmètre, mais pas faire référence aux Points _p1, _p2 ou _p3. Si nécessaire : fournir ce qu’il faut dans l’interface (accesseur get_p1, modifieur set_p1). … Triangle Mon_triangle ;

float area ;

……

area = Mon_triangle.aire(…) ;

•  Une classe Triangle_rectangle pourrait hériter de la classe triangle

Intro. / la notion de classe

Polytech Marseille , Prog. o. o. 18

Intro. / langages objets

•  Simula •  1966, compilé

•  Smalltalk •  années 72-80, interprété --> adapté au prototypage, aussi un système d’exploitation

•  C++ •  années 85, norme C++ (1998)

•  Eiffel •  1989 (un modèle de langage O.O. resté au stade universitaire)

•  Java •  années 95, interprété --> adapté au prototypage

•  Ada 95, Lisp, CLOS (Common Lisp Object System) •  C# •  Python •  PHP 5

Page 10: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

10

Polytech Marseille , Prog. o. o. 19

De C à C++

Polytech Marseille , Prog. o. o. 20

De C à C++

•  C++ est une amélioration « compatible » de C –  qui permet

•  l’abstraction de données, la programmation objet •  la généricité, la gestion des exceptions •  ...

–  beaucoup plus rigoureux que C –  fortement typé –  langage de référence normalisé –  peut être aussi rapide que C (pas de mécanisme sous-jacent complexe)

Page 11: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

11

Polytech Marseille , Prog. o. o. 21

De C à C++

•  Les moins de C++ –  la compatibilité avec C

•  langage pouvant être totalement ésotérique •  présence de deux syntaxes •  utilisation des fonctions C

–  Attention, certains points du C ANSI sont incompatibles avec C++ •  moins permissif •  prototype des fonctions •  les constantes •  …

–  langage complexe qui demande un apprentissage progressif

Polytech Marseille , Prog. o. o. 22

De C à C++

•  Il n’est pas possible de décrire toutes les possibilités de C++ –  long –  fastidieux –  certaines techniques sont à éviter

•  Il faut utiliser la documentation

–  le livre le langage C++ de B. Stroustrup contient un manuel de référence (gros !)

•  Il faut « explorer » le langage progressivement au fur et à mesure des besoins

•  Toutes les « nouveautés » de C++ ne sont pas forcément des fonctionnalités objet –  généricité, exceptions, références, redéfinition des fonctions,

fonctions inline ….

Page 12: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

12

Polytech Marseille , Prog. o. o. 23

•  Un premier programme C++

–  using namespace std ;

•  compilation et exécution (sous Unix)

De C à C++

#include <iostream> using namespace std ; int main (void) { cout << "hello the world" << endl ; return 0 ; }

libertad:~/essai_C> g++ hello.cxx -o hello libertad:~/essai_C> ./hello hello the world libertad:~/essai_C>

Remarque sur la norme ….

Polytech Marseille , Prog. o. o. 24

De C à C++

•  De nombreux mots clés réservés en plus bool catch class const_cast delete dynamic_cast explicit false friend inline mutable namespace new operator private protected public reinterpret_cast static_cast template this throw true try typeid typename using virtual wchar_t

•  Des opérateurs plus explicites and (&&) not (!) not_eq (!=) or (||) …….. (vérifier que ceux-ci sont connus du compilateur)

Page 13: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

13

Polytech Marseille , Prog. o. o. 25

De C à C++

•  Commentaires

x = y ; // commentaire qui va jusqu’a la fin de la ligne // c’est aussi un commentaire /* cela marche aussi mais pas de melange SVP */

une seule syntaxe pour les commentaires ! •  De l’importance

–  des commentaires •  explicites, complets, nombreux

–  des entêtes •  systématiques, homogènes, précis

Polytech Marseille , Prog. o. o. 26

De C à C++

•  transtypage –  il existe un transtypage explicite (à privilégier/ transtypage implicite)

en C en C++

int i = 1 ; int i = 1 ;

float x = 6.28 ; float x =6.28 ;

i = (int) x; i = int (x) ;

x = (float) i ; x = float (i) ;

le transtypage de C est parfois indispensable :

ptr1 = char *(ptr2) ; // incorrect car 2 termes ptr1 = (char *) ptr2 ;// correct

–  le transtypage a un usage précis et limité (C++ fortement typé) : ne pas en abuser

–  4 opérateurs de transtypage à usage très spécifique

Page 14: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

14

Polytech Marseille , Prog. o. o. 27

De C à C++

•  Les constantes –  oubliez le C (préprocesseur (#define), portée des constantes)

const int i = 12 ;

–  la portée de i est restreinte à l’unité de compilation contenant la définition.

Si nécessaire définir i dans un .h et inclure le fichier (#include …)

–  c’est une vraie constante –  Une constante peut être définie par une expression qui peut être évaluée

à la compilation const int nmax = 100 ;

const int max = 2 * nmax + 1 ;

–  suffixe f (ou F) (float) et u(U) unsigned

const double pi = 3.141596234134567;// les decimales ne sont pas bonnes

const float pi_court = 3.141596f ; // les constantes reelles double sinon

Polytech Marseille , Prog. o. o. 28

•  Déclaration au plus près des identificateurs –  déclaration en début de bloc (C)

–  déclaration au plus près (attention ensuite au domaine de validité) …

Prendre des règles de strictes

De C à C++

Page 15: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

15

Polytech Marseille , Prog. o. o. 29

De C à C++

#include <iostream> int main (void) { int n = 100 ; float y ; y = 10 ; float x ; x = y ; float z = y ; // attention tout de meme ! for (int i = 0 ; i < n ; i = i + 1) { int j = 10 ; n = n + i + j ; } // attention, j est maintenant inconnu // interdit d'utiliser i ainsi n = n + i + j ; return 1 ; }

libertad:~/essai_C> g++ portee.c -o portee portee.c: In function `int main()': portee.c:17: warning: name lookup of `i' changed for new ANSI `for' scoping portee.c:10: warning: using obsolete binding at `i' portee.c:17: `j' undeclared (first use this function) portee.c:17: (Each undeclared identifier is reported only once : for each function it appears in.) libertad:~/essai_C>

Polytech Marseille , Prog. o. o. 30

•  Les entrées/sorties de base : plus simples qu’en C –  <stdio.h> disponible !

–  Des flux (flots) prédéfinis dans <iostream> en particulier cin, cout, cerr : on envoie ou on récupère des informations de ces flux

De C à C++ : E/S

#include <iostream>

using namespace std ;

int main (void)

{

int i = 12 ;

float x, y ;

cout << "i=" << i << endl ;

cin >> x >> y ;

cerr << "j'avais demande des reels" << endl ;

return 1 ;

}

libertad:~/essai_C> g++ impression.c -o impression libertad:~/essai_C> ./impression i=12 3 4 j'avais demande des reels libertad:~/essai_C>

Page 16: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

16

Polytech Marseille , Prog. o. o. 31

•  Les entrées/sorties de base : chaîne de caractères

De C à C++ : E/S

#include <iostream> using namespace std ; int main(void) { char *ptr = "c'est mieux qu'en C"; char nom [128] ; int i ; i = 1 ; cout << "donner le nom et i : " ; cin >> nom >> i ; cout << "apres lecture" << nom << i <<endl ; cout << ptr << endl ; return 0 ; }

libertad:~/essai_C> g++ impression2.c -o impression2 libertad:~/essai_C> ./impression2 donner le nom et i : POLYTECH 2 apres lecturePOLYTECH2 c'est mieux qu'en C libertad:~/essai_C>

Polytech Marseille , Prog. o. o. 32

•  Portée des identificateurs ; opérateur ::

•  Attention à la portée des identificateurs et à ce genre de manipulation

De C à C++

#include <iostream> using namespace std ; int i = 0 ; // c’est le i global int main (void) { int i = 1 ; // la variable locale masque le i global cout << i << endl ; // la variable locale est affichée --> 1 cout << ::i <<endl ; // ::i fait référence à la variable globale // --> 0 { int i = 2 ; // masque les deux précédentes cout << i <<endl ; // la variable locale est affichée --> 2 cout << ::i <<endl ; // ::i fait référence uniquement à la // variable globale --> 0 } i = 3 ; // modifie le premier i local, le second // n’ayant plus d’existence return 0 ;

}

Page 17: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

17

Polytech Marseille , Prog. o. o. 33

•  Le type référence –  type dérivée de T : T & type référence vers T

•  Une valeur de type référence est une adresse

•  Trois différences avec les pointeurs 1) initialisation obligatoire 2) toute opération sur la référence agit sur l’objet référencé (pas sur

l’adresse) 3) la valeur de la référence (adresse) ne peut pas être modifiée

•  Intérêt : mécanisme d’échange entre fonctions et ….

De C à C++ : les fonctions

int ii = 0 ;

int & rr = ii ; // rr fait donc référence à ii

rr = rr + 1 ; // agit sur ce qui est référencé par rr.

// Donc ii vaut maintenant 1

Polytech Marseille , Prog. o. o. 34

Le prototypage

•  C++ est fortement typé –  contrôle systématique entre arguments et paramètres (ou paramètres

effectifs et paramètres formels) •  (en nombre, en type)

–  prototypage des fonctions est « obligatoire »

•  Utiliser le plus possible des fichiers de prototypage (.h)

De C à C++ : les fonctions

// attention la fonction puissance doit retourner une valeur

// avec une instruction return

float puissance (float x, int n);

void bidon (int m) ;

int f () ; // ces deux fonctions ne peuvent pas être appelées

int g (void) ; // avec des arguments

Page 18: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

18

Polytech Marseille , Prog. o. o. 35

Paramètres par défaut

•  On peut omettre de fournir des arguments –  si des valeurs par défaut ont été définies pour les paramètres –  ces paramètres sont les derniers –  on peut passer un argument s’il existe une valeur par défaut –  ce gère au niveau du prototype de la fonction

De C à C++ : les fonctions

#include <iostream> using namespace std ; void bidon (int, float = 10.0, int = 10) ; // ou bidon (int m, float a = 10.0, int j = 10) ; int main (void) { bidon (1, 1.0, 2) ; bidon (1, 1.0) ; bidon (1) ; return 0 ; } void bidon(int m, float a, int j) { cout << "je porte bien mon nom " << m << " " << a << " " << j) ; }

Polytech Marseille , Prog. o. o. 36

Passage des arguments - mécanisme de correspondance

•  En C++, le programmeur a la maîtrise du mécanisme

1) passage par valeur une copie de l’argument est passé à la fonction

•  problème de la copie à l'exécution (savoir le faire et temps) •  ne modifie pas l’original

De C à C++ : les fonctions

#include <iostream> void inutile (int m) { // définition directe pas de prototypage : place sur le transparent m=m+1 ; } int main (void) { int j = 0 ; inutile (j) ; // j vaut 0 après l’appel return 0 ;}

Page 19: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

19

Polytech Marseille , Prog. o. o. 37

Passage des arguments - mécanisme de correspondance

2) passage par pointeur (C) •  l’adresse de l’argument est passée •  la fonction manipule des pointeurs

De C à C++ : les fonctions

#include <iostream> void bidon (int *m) { *m = *m + 1 ; } int main (void) { int j = 0 ; bidon (&j) ; // l ’adresse de j est passée. En retour j=1 return 0 ; }

Polytech Marseille , Prog. o. o. 38

2) passage par référence (C++) •  les paramètres sont de type référence •  les arguments sont directement manipulés

De C à C++ : les fonctions

#include <iostream> void bidon (int & m) { // m est une référence m = m + 1 ; // revient à manipuler l’argument associé } int main (void) { int j = 0 ; bidon (j) ; // Manipulation de l’adresse masquée. En retour j=1 return 0 ; }

Page 20: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

20

Polytech Marseille , Prog. o. o. 39

Passage des arguments - mécanisme de correspondance

Favoriser le passage par référence : •  plus lisible •  le mécanisme à privilégier •  ajout du mécanisme const : la variable ne peut pas être modifiée

–  équivalent passage par valeur sans recopie –  permet d’éviter les recopies lourdes

De C à C++ : les fonctions

#include <iostream> void bidon (int & m, const int & l) ; // prototypage int main (void) { int j = 0 ; int l = 2 ; bidon (j, l) ; // En retour j=3 et l vaut évidemment 2 return 0 ; } void bidon (int & m, const int & l) { // m et l sont des références m = l + 1 ; // l est non modifiable }

Polytech Marseille , Prog. o. o. 40

Remarques sur l’utilisation de « const »

•  const peut aussi être utilisé pour des variables passées par valeur (indépendant du mécanisme de passage)

•  signale au compilateur qu’il ne doit pas accepter de modifier des valeurs recopiées ou signalées comme non modifiables

•  sécurité de programmation, aide à la correction de programme •  excellente habitude

•  Attention à « const type *ptr » –  Signifie ptr est un pointeur sur un objet type constant –  « type *const ptr » signifie que ptr est un pointeur constant vers un

objet type !!!

De C à C++ : les fonctions

void bidon (int & m, const float & l, const int n) { // m et l sont des références // on travaille sur une copie de n // il est interdit de modifier l et n }

Page 21: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

21

Polytech Marseille , Prog. o. o. 41

Fonctions en ligne : inline « comme une fonction classique »

•  Le compilateur insère le code de la fonction •  quand il rencontre un appel à la fonction (A PRIORI) •  permet d’économiser le mécanisme de transfert d’appel

De C à C++ : les fonctions

#include <iostream> using namespace std ; inline double valeur_abs (double x) { return ((x)>0 ? x : -x) ; } int main (void) { const double x = 4.0 ; const double x1 = -4.0 ; cout << "valeur absolue de " << x << "=" << valeur_abs (x) << endl ; cout << "valeur absolue de " << x1 << "=" << valeur_abs (x1) << endl; return 0 ; }

libertad:~/essai_C> g++ -o inline1 inline1.cxx libertad:~/essai_C> ./inline1 valeur absolue de 4= 4 valeur absolue de -4= 4 libertad:~/essai_C>

Polytech Marseille , Prog. o. o. 42

Fonctions en ligne : inline

•  Proche des macro-définitions C (toujours disponibles) •  mieux intégrées dans le langage et typées : à privilégier

De C à C++ : les fonctions

#include <iostream> using namespace std ; inline void somme_dif (const int a, const int b, int & som, int & dif) { som = a + b ; dif = a - b ; } int main (void) { const int a = 2 ; const int b = 1 ; int u, v ; somme_dif (a, b, u, v) ; cout << "a+b=" << u << endl ; cout << "a-b=" << v << endl ; return 0 ; }

libertad:~/essai_C> g++ -o inline2 inline2.cxx libertad:~/essai_C> ./inline2 a+b=3 a-b=1 libertad:~/essai_C>

Page 22: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

22

Polytech Marseille , Prog. o. o. 43

Fonctions en ligne : inline

•  des contraintes pour ces fonctions : le code de la fonction doit être disponible à la compilation –  dans le même fichier source (exemple précédent) –  dans un fichier .h inclus dans le source

•  problème du code dans un .h

–  inclus dans le .h avec un include

De C à C++ : les fonctions

// fichier inline.h inline void swap (int & a, int & b); #include "inline.hxx"

// fichier inline.hxx void swap (int & a, int & b) { int c ; c = a ; a = b ; b = c; } #include "inline.h"

int main() { int a = 1 ,b = 2 ; swap (a,b) ; return 0 ; }

Même problème pour la généricité

Polytech Marseille , Prog. o. o. 44

•  Type booléen –  le type bool prend deux valeurs « true » et « false » –  les conditions sont des expressions de type bool –  conversion implicite entre

•  true <--> 1 false <--> 0 ne pas utiliser

•  Types struct, enum, (union)

enum jours {lundi,mardi,mercredi, …} ;

struct ma_structure {…} ;

jours un_jour ; // les valeurs prises par un_jour ne sont

// pas « int »

ma_structure str ; // aussi valide

enum jours autre_jour ;

struct ma_structure autre_str ;

// conversion implicite donnant la position

int i = mercredi ; // i vaut 2

De C à C++ : les types

Page 23: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

23

Polytech Marseille , Prog. o. o. 45

•  Allocation –  new type_objet alloue un objet de type type_objet –  new type_objet[n] alloue un tableau de n objets de type type_objet

•  type-objet est quelconque •  n est une expression arithmétique quelconque

–  le résultat d’un new est de type type_objet * –  en cas de problème, il y a lancement d’une exception ...

•  Libération –  delete adresse libère l’objet alloué à l’adresse adresse –  delete [] adresse libère un tableau alloué à l’adresse adresse –  delete et delete [] ne sont pas interchangeables

•  Oubliez malloc, calloc, free ! •  N’oubliez pas que l’allocation dynamique a un coût ...

De C à C++ : allocation de mémoire

int *c ; c = new int (10) ;

int *c ; c = new int [10] ;

int *c ; c = new int [10] ; delete [] c ;

Polytech Marseille , Prog. o. o. 46

C++ et les tableaux

•  La déclaration d’un tableau utilise une expression constante –  float V[3] // tableau de 3 réels dans V[0], V[1], V[2] –  char * a[10] // tableau de 10 pointeurs de char (a[0], a[1], …, a[9] )

•  Tableaux à plusieurs dimensions (attention au nombre d’indices !) –  int mat [3][5] ; tableau de 3 vecteurs entiers de 5 éléments –  // int mat[3,5] ; est incorrect –  utilisation : mat[i][j] i = 0, … 2, j = 0, …, 4 –  en mémoire : zones de 15 entiers (dimensions utilisées par le compilateur)

void f (int ind) { int T[ind] ; // « incorrect » : ind n’est pas une expression constante // il faut dans ce cas allouer dynamiquement le tableau (voir aussi TD) // ou utiliser un composant prédéfini vector qui fait de même }

mat[0][0] mat[1][0] mat[2][0]

Page 24: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

24

Polytech Marseille , Prog. o. o. 47

•  Passage d’un tableau en paramètre #include <iostream> void f(int t[]) // evidemment t[10] convient ! { ... } int main () { int x[10] = {1,2,3,4,5,6,7,8,9,10}; f(x) ; return 0 ; }

#include <iostream> void f(int matrice[3][5]) { ... } int main () { int mat[3][5] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} ; f(mat) ; return 0 ; }

C++ et les tableaux C++ et les tableaux

Polytech Marseille , Prog. o. o. 48

•  Problème des deux (ou plus) dimensions #include <iostream> void f(int matrice[][]) // impossible { // le calcul de l’adresse de matrice[i][j] est impossible ... }

#include <iostream> void f(int matrice[][5]) { // ici le calcul de l’adresse de matrice[i][j] est possible // cette solution est valide ... }

C++ et les tableaux

Page 25: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

25

Polytech Marseille , Prog. o. o. 49

•  Problème des deux (ou plus) dimensions –  une autre solution correcte

#include <iostream> using namespace std ; const int dim_j = 5 ; void f(int matrice[][dim_j],const int & dim_i) { int i, j ; for (i = 0;i < dim_i ; i = i + 1) for (j = 0 ; j < dim_j ; j = j + 1) cout << matrice[i][j] << endl ; } int main () { int mat[3][dim_j]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} ; int dim_i = 3; f(mat, dim_i) ; return 0 ; }

C++ et les tableaux

Polytech Marseille , Prog. o. o. 50

•  Problème des deux (ou plus) dimensions –  la solution la plus générale

–  On se substitue au compilateur ! –  Pas « élégant » –  Différent dans d’autres langages

#include <iostream> using namespace std ; void f(int v[],const int & dim_i, const int & dim_j) { int i, j ; for (i = 0;i < dim_i ; i = i + 1) for (j = 0 ; j < dim_j ; j = j + 1) cout << v[i*dim_j+j] << endl ; // vérifiez le calcul ! } int main () { int mat[3][5] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} ; int dim_i = 3, dim_j = 5 ; f(&mat[0][0], dim_i, dim_j) ; return 0 ; }

C++ et les tableaux

Page 26: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

26

Polytech Marseille , Prog. o. o. 51

•  Mémoire allouée à l’éxécution –  ne pas oublier de désallouer

à la fin de l’utilisation

•  Cas du tableau à plusieurs dimensions –  tableau de tableaux de taille connue à la compilation

#include <iostream> main() { int (*mat)[4]; // le type est int (*) [4] ; int i,j ; i=3 ; mat = new int[i][4]; // on utilise ensuite mat[i][j] }

C++ et les tableaux dynamiques

int *c ; c = new int [10] ; // int d[] ; est incorrect … delete [] c ;

// new int [4][i] non : 4 éléments d’un tableau de taille «variable» // new int [i][j] non new int [i][4][5] // oui avec un type int (*)[4][5] // new int [4][i][5] // non // new int [4][5][i] // non

Polytech Marseille , Prog. o. o. 52

•  Cas du tableau à plusieurs dimensions (2 !) –  tableau de tableaux de tailles connues à l'exécution

#include<iostream> using namespace std ; int main() { int l, c ; // On prend un tableau de l lignes et c colonnes int ** mat ; // pointeur sur un pointeur l = 3 ; c = 4 ; // tableau des pointeurs vers les vecteurs de c éléments mat=new int*[l]; // allocation des l vecteurs de c éléments for (int i = 0 ; i < l ; i = i +1) { mat[i]=new int[c]; for (int j = 0 ; j < c ; j = j +1) mat[i][j]= i + j; } for (int i = 0 ; i < l ; i = i + 1) { for (int j = 0 ; j < c ; j = j + 1) cout << mat[i][j] << "\t" ; cout << "\n" ; } }

C++ et les tableaux dynamiques

Page 27: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

27

Polytech Marseille , Prog. o. o. 53

•  Passage du tableau en paramètre

#include <iostream> void f(int **m, const int & dim_i, const int & dim_j) { // int m[][] n'est pas acceptable for (int i = 0 ; i < dim_i ; i = i + 1) for (int j = 0 ; j < dim_j ; j = j + 1) { } // on peut utiliser ici m[i][j] } int main() { int l, c ; int ** mat ; l = 3 ; c = 4 ; // tableau des pointeurs vers les vecteurs de c éléments mat=new int*[l]; // allocation des l vecteurs de c éléments for (int i = 0 ; i < l ; i = i +1) { mat[i]=new int[c]; for (int j = 0 ; j < c ; j = j +1) mat[i][j]= i + j; } f(mat, l, c) ; return 0 ;}

C++ et les tableaux dynamiques

Polytech Marseille , Prog. o. o. 54

•  Surcharge des fonctions –  offrir plusieurs définitions d’une même fonction (attention aux ambiguïtés)

•  les types et/ou le nombre des paramètres doivent être différents : signature •  dans ces conditions, la valeur de retour peut être différente •  le choix de la fonction est géré en fonction des arguments

int max(const int, const int) ; // max de 2 entiers

int max (const int, const int, const int) ; // max de 3 entiers

// le max du tableau nombre d’éléments : 2ème paramètre

int max(const int [], const int)

// double max(const int, const int) est illégal

// légal le type des paramètres est différent des précédents

double max(const double, const double) ;

// il reste à définir les différentes fonctions

•  Attention à ce que la surcharge ait « un sens »

De C à C++ : surcharges

Page 28: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

28

Polytech Marseille , Prog. o. o. 55

Les concepts des langages de classes ; implémentation en C++

Polytech Marseille , Prog. o. o. 56

Les classes : introduction

•  Une classe est une implémentation d’un type abstrait de données

•  Les classes possèdent : –  des données membres (les attributs) –  des fonctions membres (les méthodes)

•  Le nom de la classe est le spécificateur de type

•  Les objets de type X sont des instances de la classe X

•  Au delà des principes généraux il faut un langage d’implémentation –  C++ est un langage difficile et complet –  des variations suivant les langages (en particulier avec Java)

Page 29: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

29

Polytech Marseille , Prog. o. o. 57

Les classes : introduction

Masquage de l’information

•  Séparation : –  membres et fonctions membres accessibles de l’objet

(partie publique) –  membres et fonctions membres propres de l’objet

(partie privée)

•  L’implémentation d’un objet peut être modifiée sans affecter les applications qui manipulent l’objet –  données membres, fonctions membres

Partie privée

Partie publique Vision de l’utilisateur de la classe

Vision du concepteur de la classe

Polytech Marseille , Prog. o. o. 58

Masquage de l’information

•  il s’effectue à 3 niveaux –  public –  protected –  private (c’est le statut par défaut)

•  Attention, protection au niveau de la classe, pas de l’objet •  une fonction membre accède aux données privées de tout objet de la même

classe

Les classes : introduction

public

protected Accessible aux héritiers

Accessible à la classe

private

Accessible à tous

Page 30: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

30

Polytech Marseille , Prog. o. o. 59

Les classes : introduction

Une classe est une unité de compilation

•  un fichier entête (Classe.h) qui définit la classe (appelé interface)

•  un fichier source (Classe.cxx) qui contient l’implémentation des fonctions membres

•  l’implémentation des fonctions peut se faire dans l’entête. Les fonctions sont alors inline par défaut

(se justifie pour des fonctions très courtes)

•  Une fonction implémentée dans Classe.cxx –  doit être qualifiée par le nom de la classe par l’opérateur de résolution de

portée ::

type Classe::fonction_membre(signature) { …}

Polytech Marseille , Prog. o. o. 60

Une première classe : une classe Point •  deux attributs réels

–  abscisse x et ordonnée y

•  en première approche, il faut –  initialiser un point avec deux réels –  déplacer un point de dx, dy –  afficher les coordonnées du point

Les classes : introduction

Page 31: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

31

Polytech Marseille , Prog. o. o. 61

Interface de la classe Point (version 1) : Point1.h •  Impossible de consulter ni de modifier les coordonnées •  On peut prévoir des accesseurs (get_x, get_y) ou modifieurs

(set_x, set_y)

Les classes : introduction

// interface de la classe Point class Point { private : // on aurait pu choisir de déclarer x et y protected float _x, _y ; public : void initialiser (float, float) ; void deplacer (float, float) ; void afficher (void) ; } ;

Polytech Marseille , Prog. o. o. 62

Implémentation de la classe Point (version 1) : Point1.cxx

Les classes : introduction

// implémentation des fonctions membres de la classe Point // #include <iostream> using namespace std ; #include "Point1.h" void Point::initialiser (float abscisse, float ordonnee) { _x = abscisse ; _y = ordonnee ; } void Point::deplacer(float dx, float dy) { _x = _x + dx ; _y = _y + dy ; } void Point::afficher(void) { cout << "les coordonnees du point sont : (" << _x << "," << _y << ")" << endl ; }

Page 32: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

32

Polytech Marseille , Prog. o. o. 63

Appel de la classe point (version 1) : essai_Point1.cxx

Les classes : introduction

#include "point1.h" using namespace std ; int main (void) { // déclaration d'un objet point, instance de la classe point Point p ; // remarquez comment s'appelle une fonction membre p.initialiser (1.0f, 2.0f) ; p.afficher () ; p.deplacer (0.1f, -0.1f) ; p.afficher () ; return 1 ; }

libertad:~/essai_C> g++ -c Point1.cxx libertad:~/essai_C> g++ -c essai_Point1.cxx libertad:~/essai_C> g++ -o essai_Point1 essai_Point1.o Point1.o libertad:~/essai_C> ./essai_Point1 les coordonnees du point sont : (1,2) les coordonnees du point sont : (1.1,1.9) libertad:~/essai_C>

Polytech Marseille , Prog. o. o. 64

Les classes : vie d’un objet

•  Un objet, instance d’une classe est :

–  créé

–  initialisé

–  utilisé •  consulté •  modifié

–  libéré

–  détruit

•  Les constructeurs et le destructeur sont des fonctions membres particulières

A l’aide d’un des constructeurs * (par défaut) * ou géré par le concepteur

Fonctions membres

A l’aide d’un destructeur géré par le concepteur

Page 33: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

33

Polytech Marseille , Prog. o. o. 65

Les classes : vie d’un objet

•  Un constructeur est une fonction membre dont le nom est le même que celui de la classe

•  Un constructeur n’a pas de type

•  On peut avoir plusieurs constructeurs

•  En fonction du nombre et du type des arguments passés à l’appel, le bon constructeur est choisi

•  Dès qu’il existe un constructeur explicite, le constructeur par défaut de C++ n’est plus accessible

Polytech Marseille , Prog. o. o. 66

Les classes : vie d’un objet

•  Un premier exemple de constructeur (1/2)

// interface de la classe Point class Point { private : float _x, _y ; public : Point (float, float) ; void initialiser (float, float) ; void deplacer (float, float) ; void afficher (void) ; Point fonction_membre (…) ; } ;

Page 34: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

34

Polytech Marseille , Prog. o. o. 67

Les classes : vie d’un objet

•  Un premier exemple de constructeur (2/2)

•  On peut aussi utiliser le constructeur

–  attention à la recopie ...

// implémentation des fonctions membres de la classe Point // #include "Point1.h" #include <iostream> Point::Point (float abscisse, float ordonnee) { _x = abscisse ; _y = ordonnee ; } … Point Point::fonction_membre (…) { … return Point (a, b) ; // ce qui crée un nouveau point }

Point p1 (1.0f, 1.0f) ; Point p2 = Point (1.0f, 2.0f) ;

Polytech Marseille , Prog. o. o. 68

Les classes : différents objets

•  Objets statiques –  variables globales ou objets déclarés static. Définis à la compilation

•  durée de vie = durée de l’exécution du programme

•  Objets automatiques –  variables locales.

•  Appel constructeur : au moment de la définition de l’objet •  Appel destructeur : fin de portée de l’objet

•  Objets dynamiques –  définis par un pointeur sur une zone allouée par new

•  durée de vie entre le new et le delete

Page 35: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

35

Polytech Marseille , Prog. o. o. 69

Les classes : différents objets

•  Objets temporaires –  créés à l’exécution ( ex : return (Point (a, b) ) ; )

–  création d’un objet temporaire sans nom •  Appel constructeur : au moment de la définition de l’objet •  Appel destructeur : fin de l’expression la plus englobante contenant l’objet

–  créés par le compilateur (calculs intermédiaires) •  Nécessite la définition d’un constructeur par recopie

Polytech Marseille , Prog. o. o. 70

Les classes : this

•  Paramètre caché de toutes les fonctions membres : this

•  implicitement défini (auto-référencé)

•  this est un pointeur sur l’objet manipulé –  this –  *this

•  Son usage est implicite ou explicite

•  Accessible à toutes les fonctions membres (non statiques)

Page 36: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

36

Polytech Marseille , Prog. o. o. 71

Les classes : this

Exemples d’utilisation

•  L’utilisation de « this » est parfois réellement indispensable

–  ex : return *this ;

// implémentation des fonctions membres de la classe Point // #include "Point1.h" void Point::initialiser (float _x, float ordonnee) { this->_x = _x ; // indispensable car _x paramètre cache // le membre _x !! this ->_y = ordonnee ; // correct mais inutile } void Point::deplacer (float dx, float dy) { this->_x = this->_x + dx ; // pourquoi faire simple this->_y = this->_y + dy ; // c’est totalement inutile ici }

Polytech Marseille , Prog. o. o. 72

Les classes : constructeurs

Trois constructeurs (1/2)

•  Le constructeur par défaut –  pas de constructeur proposé

•  toujours un synthétisé par le compilateur (peut-être dangereux)

–  un constructeur sans paramètre proposé –  un constructeur ayant tous ses paramètres par défaut

•  le constructeur par défaut doit pouvoir être appelé sans paramètre –  Il est appelé automatiquement dans certaines situations (ex. objets

membres)

•  Le constructeur avec initialisation –  voir l’exemple de la classe Point

Page 37: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

37

Polytech Marseille , Prog. o. o. 73

Les classes : constructeurs

Trois constructeurs (2/2)

•  Le constructeur par recopie (d’un autre objet) –  le premier paramètre est une référence de l’objet à cloner

classe::classe (const classe & cloneur, .) ou classe::classe (classe & cloneur, …)

•  & : pour la « recopie » éventuelle des zones dynamiques de l’objet •  Ne peut pas être passé par copie puisque c’est ce que l’on cherche à définir ! •  s’il y a d’autres paramètres, ils doivent tous avoir des valeurs par défaut •  const obligatoire dans certains cas (objets sans nom retourner par recopie)

–  Il est conseillé d’avoir un constructeur par recopie •  évite la synthétisation automatique erronée par le compilateur

(cas complexes)

•  L’appel à un constructeur suit la création de l’objet –  en particulier : il a sa place mémoire (sauf les parties dynamiques

éventuelles)

Polytech Marseille , Prog. o. o. 74

Les classes : constructeurs

Un cas particulier important (1/2)

•  Les membres de la classe sont des objets (objets membres) –  Comment initialiser les objets membres ? (au moment de leur

création)

class Segment { Point a, b ; public : Segment (float, float, float, float) ; … }; … Segment::Segment (float x1, float y1, float x2, float y2) : a (x1, y1), b (x2, y2) { …} // ainsi les points a et b sont initialisés …

–  On peut faire de même pour les membres de type scalaire

Page 38: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

38

Polytech Marseille , Prog. o. o. 75

Les classes : constructeurs

Un cas particulier important (2/2)

•  Cas de la constante membre (non déclarée static) –  Comment initialiser la constante membre ?

class Complexe { const bool reel ; float _a,_b ; … public : Complexe (float xx, float yy) : reel (false) {…} Complexe (float xx) : reel (true) {…} ... };

–  reel est initialisée à la création et ne peut plus être modifiée

•  Même problème pour les membres de type reference

Polytech Marseille , Prog. o. o. 76

Les classes : destructeur

Le destructeur •  le destructeur de la classe « Classe » est la fonction membre

de nom : ~Classe (void)

•  Il n’a pas de type ni de paramètre

•  Il libère en particulier la mémoire allouée

•  L’appel au destructeur précède la destruction de l’objet

•  Une classe peut ne pas avoir de destructeur –  toujours un synthétisé par le compilateur (peut être dangereux)

Page 39: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

39

Polytech Marseille , Prog. o. o. 77

Les classes : synthèse constructeurs et destructeur

Interface de la classe Point (version 2) : point2.h // interface de la classe Point class Point { float _x, _y ; public : // les constructeurs Point (void) ; // constructeur par défaut Point (const float) ; // un deuxième constructeur Point (const float, const float) ; // encore une surcharge Point (const Point &) ; // constructeur par recopie // ce constructeur pourrait // avoir d’autres paramètres // avec des valeurs par défaut ! void initialiser (float, float) ; void deplacer (float, float) ; void afficher (void) ; // le destructeur ~Point (void) ; };

Polytech Marseille , Prog. o. o. 78

Les classes : synthèse constructeurs et destructeur

Implémentation de la classe Point (version 2) : Point2.cxx // implémentation des fonctions membres de la classe Point // #include <iostream> #include "Point2.h" using namespace std ; Point::Point(void) { _x = 0.0 ; _y = 0.0 ; cout << "constructeur par defaut" << endl ; } // ou Point::Point(void): _x(0),_y(0) {…} Point::Point(const float r) { _x=r ; _y=r ; cout << "constructeur 1 parametre" << endl ; } // ou Point::Point(const float r): _x(r),_y(r) {…} ...

Point::Point(const float r, const float t) { _x = r ; _ y = t ; cout << "constructeur 2 parametres" << endl ; } // ou Point::Point(const float r, const float t) : _x(r),_y(t) { …} Point::Point (const point & p) { _x = p._x ; _y = p._y ; cout << "constructeur par recopie" << endl ; } Point::~Point (void) { cout << "destructeur" << endl ; } ...

Page 40: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

40

Polytech Marseille , Prog. o. o. 79

Appel de la classe Point (version 2) : essai_point2.cxx

Les classes : synthèse constructeurs et destructeur

#include "Point2.h" Point a ; //------------------------------------ Point creepoint(void) { Point p = Point (7.0, 8.0) ; return (p) ; } //------------------------------------ int main(void) { Point b(5.0), c(5.0, 2.0), e(b), f = c ; Point * d ; a.afficher( ); b.afficher( ); c.afficher( ); d=new Point(6.0); d->afficher( ); delete d ; e.afficher( ); f.afficher( ); f =creepoint( ); f.afficher( ); return 1 ; }

libertad:~/essai_C> ./essai_point2 constructeur par defaut constructeur 1 parametre constructeur 2 parametres constructeur par recopie constructeur par recopie les coordonnees du point sont : (0,0) les coordonnees du point sont : (5,5) les coordonnees du point sont : (5,2) constructeur 1 parametre les coordonnees du point sont : (6,6) destructeur les coordonnees du point sont : (5,5) les coordonnees du point sont : (5,2) constructeur 2 parametres constructeur par recopie destructeur destructeur les coordonnees du point sont : (7,8) destructeur destructeur destructeur destructeur destructeur libertad:~/essai_C>

?

?

Polytech Marseille , Prog. o. o. 80

Les classes : opérations par défaut

On peut : •  Instancier des objets et utiliser un constructeur :

class C { …} ; // déclaration de la classe C ... C objet1, objet2 ;

•  Pointer sur un objet Faire référence à un objet C * p ; C & ref = objet2 ; p = & objet1 ;

•  Affecter un objet objet1= objet2 ;

–  lors de l’affectation, il n’y a pas, par défaut, de recopie de la partie dynamique éventuelle. Il y a juste affectation du pointeur

–  Si nécessaire, gestion explicite obligatoire par surcharge de l’opérateur d’affectation

Page 41: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

41

Polytech Marseille , Prog. o. o. 81

Variable membre statique •  Variable partagée par tous les objets de la classe

–  stockée à un seul endroit et initialisée •  hors de la classe et hors de toute fonction membre

•  Il existe aussi des constantes membres static

Les classes : membres statiques

// interface de la classe Point class Point { float _x, _y ; static int _nb_points ; // ou public public : // les constructeurs Point(void) ; ... // le destructeur ~Point(void) ; };

// fonctions membres de la classe Point int Point::_nb_points = 0 ; Point::Point(void) { _x = 0.0 ; _y = 0.0 ; _nb_points = _nb_points + 1 ; } Point::~Point(void) { _nb_points = _nb_points - 1 ; } ...

Polytech Marseille , Prog. o. o. 82

Fonction membre constante : important •  Fonction qui peut consulter l’objet mais pas le modifier

type Classe::nom_fonction (signature) const ;

•  Peut s’appliquer sur un objet const (autrement : illégal)

•  Conséquence fondamentale –  à suivre ….

Les classes : fonctions membres

// interface de la classe Complexe class Complexe { float _a, _b ; public : ... float get_a(void) const { return _a ; } float get_b(void) { return _b ; } };

#include "Complexe.h" …. const Complexe c(1.0,1.0) ; float x = c.get_a () ; // autorisé // float y = c.get_b () ; est illégal

void ma_fonction(.., const Complexe x) { // float y = x.get_b () ; est illégal }

Page 42: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

42

Polytech Marseille , Prog. o. o. 83

Fonction membre statique •  Fonction qui manipule des membres statiques et peut ainsi être déclarée

static –  utilisable partout par la référence à la classe –  pas d’accès à this

Les classes : fonctions membres

// interface de la classe Point class Point { float _x, _y ; static int _nb_points ; public : … static void afficher_compteur(void) ; };

// fonctions membres de la classe Point int Point::_nb_points = 0 ; void Point::afficher_compteur(void) { cout << _nb_points << endl ; } ...

// peut ensuite être appelée // n’importe où ... Point::afficher_compteur() ; ...

Polytech Marseille , Prog. o. o. 84

Les classes : des membres et fonctions membres !

On peut aussi avoir :

•  des membres mutable –  modifiable même s’il appartient à un objet const

•  (ex : nb_consultations d’un objet)

•  des pointeurs sur des membres

•  des pointeurs sur des fonctions membres –  l’identificateur d’une fonction est un pointeur –  la valeur du pointeur peut changer

•  même syntaxe pour différents appels !

•  « lire la doc ! »

Page 43: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

43

Polytech Marseille , Prog. o. o. 85

Les classes : tableaux d’objets

•  On peut créer des tableaux d’objets –  à 1, 2 ou n indices –  conformes aux tableaux vus dans la partie précédente –  statiques, automatiques ou dynamiques

•  Une bonne règle : l’objet doit avoir un constructeur par défaut

•  On peut créer des opérations de « haut niveau » !

class Complexe { … public Complexe(float = 0.0, float = 0.0) ; // constructeur par défaut … };

…. Complexe ztab[100] ; ...

Polytech Marseille , Prog. o. o. 86

Les classes : l’amitié en C++

•  Une entorse aux concepts de Programmation Orientée Objets …

•  la partie private est réservée aux instances de la classe.

•  Les amis ou friend permettent de casser le mécanisme d’encapsulation et d’accéder aux informations de la classe

•  Les friend peuvent être : –  des fonctions indépendantes –  des fonctions membres d’une autre classe –  des fonctions amies de plusieurs classes –  des classes amies

•  L’abus des « friend » est dangereux. A consommer avec modération ! Si trop d’amis : repenser les objets

Page 44: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

44

Polytech Marseille , Prog. o. o. 87

Les classes : l’amitié en C++

•  Un exemple pour « améliorer la performance »

class Tableau { int *tab, taille ; // définie ici ou en partie public friend void print(const Tableau &) ; public : Tableau(int n = 10) { taille = n ; tab = new int [taille] ; } // lancement d’une exception si problème d’accès int & element(int i) { assert ( i < taille) ; return tab[i] ; }

… } ; void print(const Tableau & t) { // « plus rapide » que de passer par la fonction membre element for (int i = 0 ; i < t.taille ; i = i + 1) cout << t.tab [i] ; }

Polytech Marseille , Prog. o. o. 88

•  Un exemple de classe amie : une liste de chainons

class Chainon { char *donnee ; // ou char donnee ; Chainon * suivant ; friend class Liste ; } ; class Liste { Chainon * tete ; public : Liste (void) { tete = new Chainon ; tete->suivant = NULL ; // accès au membre privé de tete } } ;

•  Remarque : exemple incomplet pour être opérationnel

Les classes : l’amitié en C++

Page 45: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

45

Polytech Marseille , Prog. o. o. 89

Les classes : l’amitié en C++

•  Attention : Les amis de mes amis ne sont pas mes amis

class A { static const int _n = 100 ; friend class B ; } ; // la définition de la classe B est correcte class B { float tab[A::_n] ; friend class C ; } ; // la définition de la classe C est incorrecte // il faudrait que C soit amie de A class C { int t [A::_n] ; } ;

Polytech Marseille , Prog. o. o. 90

Les opérateurs

•  Idée : étendre les opérateurs de base pour qu’ils puissent s’appliquer aux objets –  (ex : pour 2 complexes z1 et z2 z1 = = z2 z1 + z 2 )

•  Il existe des opérateurs –  unaires &, new –  binaires = =, <, <<, >> –  unaires et binaires +, -, * (pointeur), * (multiplication)

•  Les opérateurs ont un ordre de précédence (priorité) –  z = a * b + c ; veut dire a * b

puis (a * b) + c puis z = le résultat

–  l’utilisation des parenthèses lève les ambiguïtés z = (a * b) + c ;

Page 46: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

46

Polytech Marseille , Prog. o. o. 91

Les opérateurs

•  Les opérateurs unaires sont associatifs à droite *p++ ; veut dire *(p++) ; (sans commentaire !)

= est associatif à droite : a = b = c veut dire a = (b = c)

•  Les opérateurs binaires sont associatifs à gauche a + b + c ; veut dire (a + b) + c ;

•  « lire la doc ! » pour –  liste des opérateurs –  les ordres de précédence

•  La programmation explicite des précédences et associativités est la règle pour les cas non triviaux

Polytech Marseille , Prog. o. o. 92

Les opérateurs

•  Les opérateurs prédéfinis peuvent être redéfinis pour les types de l’utilisateur donc pour les objets

•  Les opérateurs sont des fonctions x = y + z ; veut dire operator= (x, operator+ (y, z) ) ;

•  Surcharger un opérateur : créer une nouvelle fonction –  les règles des fonctions sont conservées –  les précédences, arités et associativités ne peuvent être modifiées –  ne conserve pas nécessairement l’éventuelle commutativité

•  Il est impossible de créer de nouveaux opérateurs

•  Les opérateurs d’affectation (=) et d’adressage (&) sont implicitement définis, mais peuvent être redéfinis –  attention à l’implicite, ex : objet avec partie dynamique

Page 47: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

47

Polytech Marseille , Prog. o. o. 93

Les opérateurs

•  Les opérateurs ne peuvent pas être surchargés pour les types prédéfinis (int, …)

•  Pas de surcharge possible pour –  . Sélection de membre ( objet.membre ) –  .* ( objet.pointeur_de_membre ) –  :: résolution de portée ( Classe::nom ) , global ( ::nom ) –  ? : expression conditionnelle ( x>0 ? x : -x ) –  sizeof taille de l’objet ( sizeof expr ), d’un type (sizeof (type) ) –  #, ## gérés par le préprocesseur

Polytech Marseille , Prog. o. o. 94

Deux implémentations possibles, mais différentes (1/2)

•  redéfinir l’opérateur par une fonction membre –  implicitement, l’opérateur redéfini a un paramètre de plus (this) –  pas de symétrie naturelle -> pas commutatif –  si le membre gauche est d’une autre classe : impossible –  non static (sauf éventuellement new, new [], delete, delete [])

class Complexe { float _a, _b ; public : Complexe(float = 0.0, float = 0.0) ; Complexe operator+(const Complexe &) ; … } ;

Complexe Complexe::operator+(const Complexe &z) { return Complexe (_a + z._a, _b +z._b) ; }

Les opérateurs

… Complexe z1, z2, z3 ; float x ; // possible z3 = z1 + z2 ; // possible avec conversion // implicite de type // x-> complexe (avec un // constructeur 1 paramètre) z3 = z1 + x ; // impossible, même avec // la conversion implicite z3 = x + z1 ;

Page 48: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

48

Polytech Marseille , Prog. o. o. 95

Les opérateurs

… Complexe z1 ; Complexe z2 ; Complexe z3 ; float x ; // possible z3 = z1 + z2 ; // possible avec // la conversion // implicite de x z3 = x + z1 ; z3 = z1 + x ;

Deux implémentations possibles, mais différentes (2/2)

•  redéfinir l’opérateur par une fonction non membre –  la fonction « doit être » amie pour accéder simplement aux membres –  symétrie naturelle –  plus d’accès à this class Complexe { float _a, _b ; public : Complexe(float = 0.0, float = 0.0) ; friend Complexe operator+(const Complexe &, const Complexe &) ; … } ;

Complexe operator+(const Complexe & z1, const Complexe & z2) { return Complexe(z1._a + z2._a, z1. _b +z2._b) ; }

Polytech Marseille , Prog. o. o. 96

Les opérateurs

Point & operator = (const Point & p) { _x = p._x ; _y = p._y ; return *this ; // pourquoi * this ? }

opérateur d’affectation

•  Le type de retour d’une expression d’affectation est le type de l’opérande gauche avec une référence pour éviter la copie

•  L’opérande gauche « doit » être une lvalue modifiable –  Pour pouvoir affecter !

•  Ne pas confondre a = b ; et Point a = b ;

•  Attention, par défaut un opérateur d’affectation est synthétisé –  Copie membre à membre ….. y compris les pointeurs sur les parties dynamiques

On pourrait écrire : void operator= (…) mais a=b=c soit : a=(b=c) serait impossible Point operator = (…) mais a=b=c impliquerait la copie de b

Page 49: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

49

Polytech Marseille , Prog. o. o. 97

lvalue et fonction de type référence

•  A l’origine (d’autant que C++11 modifie les choses) « Une lvalue est quelque chose qui peut être du côté gauche d’une affectation » (par opposition à une rvalue)

•  Plus précisément « Un objet est une région de mémoire ; une lvalue est une expression qui fait

référence à une zone mémoire », qui a donc une persistence dans le temps. On ne peut pas tout faire avec des rvalues !

•  Une lvalue peut être modifiable ou non (par exemple si elle est déclarée constante)

•  Certains opérateurs produisent des lvalues

•  Une fonction de type référence est une fonction retournant une lvalue, quelque chose qui « reste »

–  Et qui évite une recopie

Les opérateurs

int & f(….) {...} // f retourne une lvalue de type int

i=3 ; lvalue= rvalue ;

Polytech Marseille , Prog. o. o. 98

opérateur d’indexation

•  Permet d’accéder directement aux éléments d’un tableau à l’extérieur de la classe

Les opérateurs

#include <iostream> using namespace std ; class Vecteur { private :

int _T[10]; public :

Vecteur(){ …} int & operator[](const int & i) { return _T[i] ;}

}; int main () { Vecteur t ; int i = 1; //cout << t._T[1] ; // accès à un variable privée; OK si en public cout << t[i] <<endl; t[i] = 100 ; // possible car [] retourne une lvalue // le moyen d ’accès à _T a été donné en public return 1 }

Page 50: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

50

Polytech Marseille , Prog. o. o. 99

Comment choisir ?

•  Cela dépend –  des besoins de conception de la classe

•  fonction membre <-> accès possible à this

–  des besoins des utilisateurs •  fonction non membre <-> symétrie naturelle : à privilégier pour les opérateurs

commutatifs

•  Des contraintes imposées par le langage

•  Une règle :

•  = ( ) [] -> nécessairement fonctions membres •  Opérateur unaire fonction membre •  Opérateur d’affectation fonction membre •  Opérateur binaire fonction non membre amie

Les opérateurs

Polytech Marseille , Prog. o. o. 100

Il est sage de :

•  Redéfinir l’opérateur d’affectation (avec retour d’une référence)

•  Redéfinir les opérateurs d’égalité (==) et de différence (!= ou not_eq)

•  Redéfinir l’opérateur << vers le flot de sortie voire même >> en provenance du flot d’entrée •  Redéfinir l’opérateur d’indexation peut être bien pratique

Les opérateurs

Page 51: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

51

Polytech Marseille , Prog. o. o. 101

Les opérateurs

Il est tout aussi sage de :

•  Respecter la sémantique habituelle des opérateurs

•  Respecter les relations entre les opérateurs = = et not_eq (!=)

bool Classe::operator ==(const Classe &) const {} // à définir bool Classe::operator !=(const Classe &c) const // ou not_eq { return (not(operator==(c))) ; // ou ( not ((*this)==c)) ; }

<, <=, >, >=

bool Classe::operator <(const Classe &) const {} // à définir bool Classe::operator >=(const Classe &c) const { return ( not(c <(*this))) ; }

–  Remarque dans <utility>, les opérateurs !=,>,>=,<= sont définis de façon générique dès que == et < sont définis pour la classe (voir généricité plus loin) et contraintes d’utilisation en TD

Polytech Marseille , Prog. o. o. 102

Les opérateurs

Surcharge des opérateurs d’entrée/sortie << et >> (1/2)

•  surcharge de << –  défini initialement dans la classe ostream (classe non modifiable) –  définir la surcharge sous une des formes suivantes

•  ostream & operator << (ostream &, Classe) ; •  ostream & operator << (ostream &, Classe &) ; •  ostream & operator << (ostream &, const Classe &) ; •  & permet d’écrire cout << a << b << c; ßà ((cout << a) << b) << c ;

–  en fonction amie de la classe (le premier paramètre n’est pas un objet de la classe et pour accéder à tout) (pour plus de « simplicité »)

class Point { float _x, _y ; friend ostream & operator << (ostream & flot, const Point & p) { // le problème n’est pas de savoir si un point doit s’écrire ainsi ! // return ( flot << "les coordonnees sont (" << p._x << " , " << p._y <<

" ) ") ; } ...

Page 52: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

52

Polytech Marseille , Prog. o. o. 103

Les opérateurs

Surcharge des opérateurs d’entrée/sortie << et >> (2/2)

•  surcharge de >> –  défini initialement dans la classe istream (classe non modifiable) –  définir la surcharge sous la forme

•  istream & operator >> (istream &, Classe &) ;

–  en fonction amie de la classe (le premier paramètre n’est pas un objet de la classe) (amie ou non : choix d’implémentation)

class Point { float _x, _y ; friend istream & operator >> (istream & flot, Point & p) { // le problème n’est pas de savoir si un point doit se lire ainsi ! // return ( flot >> p._x >> p._y ) ; // ou flot >> p._x >> p._y ; ….. ; return flot ; } ...

Polytech Marseille , Prog. o. o. 104

L’héritage : principes

•  Si une classe B est définie à partir de A –  A est la classe de base de B –  B est la classe dérivée de A

•  Une classe de base –  peut être une classe dérivée –  peut avoir plusieurs classes dérivées

•  Une classe de base A est accessible pour C si –  A est une classe de base de C –  les membres publics de A sont accessibles aux utilisateurs de C –  C offre les mêmes services que A

•  Trois types d’héritage : privé, protégé et public

Page 53: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

53

Polytech Marseille , Prog. o. o. 105

L’héritage : principes

•  héritage d’une classe de base = héritage simple •  héritage de plusieurs classes de base = héritage multiple

•  ex de relation d’héritage

FigureGeometrique

Polygone Ellipse

Parallelogramme Triangle Cercle Rectangle Losange

Carre

Héritage simple

Héritage multiple

Remarquer la difficulté pour l’héritage de carré

Polytech Marseille , Prog. o. o. 106

L’héritage : principes

L’héritage permet

•  D’accéder à ce qui est déjà défini –  en accord avec le type d’héritage retenu (privé, protégé et public)

•  De spécialiser la classe –  redéfinition des membres –  redéfinition des fonctions membres

•  D’enrichir la classe avec –  de nouveaux membres –  de nouvelles fonctions membres

Page 54: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

54

Polytech Marseille , Prog. o. o. 107

L’héritage : principes

Schéma général d’une classe et de l’héritage

public

protégé Accessible aux héritiers

Accessible au concepteur de la classe

privé

Accessible à tous

Partie inaccessible héritée

Polytech Marseille , Prog. o. o. 108

•  L’héritage par défaut

•  Les utilisateurs de B « ne peuvent rien utiliser » de A

•  Utilisation : La déclaration de B s’appuie sur celle de A, mais un objet de B n’est pas vu comme « une sorte de A »

L’héritage privé

public

protégé

privé

Partie inaccessible héritée

protégé

privé

Partie inaccessible héritée

public

Classe de base A Classe dérivée B Obtenue par héritage privé

Page 55: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

55

Polytech Marseille , Prog. o. o. 109

L’héritage privé

•  Déclaration : class A { … } ;

class B : private A ou class B : A { { … … } ; } ;

•  « Aménagement » class B : private A { public :

using A::variable_publique ; // le membre public de A devient ainsi // public de B …

} ;

Polytech Marseille , Prog. o. o. 110

L’héritage privé

class A { int priv ; protected : int prot ; public : int pub ; } ; class B : private A { public : void f (void) { priv = 1 ; prot = 1 ; pub = 1 ; } } ;

class C : private B { public : void g (void) { priv = 1 ; prot = 1 ; pub = 1 ; B b ; } } ; int main (void) { B b ; b.priv = 1 ; b.prot = 1 ; b.pub = 1 ; return 1 ; }

Page 56: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

56

Polytech Marseille , Prog. o. o. 111

L’héritage privé

class A { int priv ; protected : int prot ; public : int pub ; } ; class B : private A { public : void f (void) { // priv = 1 ; prot = 1 ; pub = 1 ; } } ;

class C : private B { public : void g (void) { // priv = 1 ; // prot = 1 ; // pub = 1 ; B b ; } } ; int main (void) { B b ; // b.priv = 1 ; // b.prot = 1 ; // b.pub = 1 ; return 1 ; }

Remarque : même résultat avec : « class C : public B »

Pour accéder à priv à partir de B, il faut passer par une fonction

membre de A

Polytech Marseille , Prog. o. o. 112

•  Héritage moins restrictif

•  Les utilisateurs de B « ne peuvent rien utiliser » de A, mais les héritiers de B « ont des accès » aux membres de A

•  Utilisation : Restriction pour les utilisateurs de B, mais droits complets pour les héritiers de B

L’héritage protégé

public

protégé

privé

Partie inaccessible héritée

protégé

privé

Partie inaccessible héritée

public

Classe de base A Classe dérivée B

Obtenue par héritage protégé

Page 57: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

57

Polytech Marseille , Prog. o. o. 113

L’héritage protégé

•  Déclaration : class A { … } ; class B : protected A { … } ;

•  « Aménagement » class B : protected A { public :

using A::variable_publique ; // le membre public de A devient ainsi // public de B using A::variable_protegee ; // le membre protege de A devient ainsi // public de B …

} ;

Polytech Marseille , Prog. o. o. 114

L’héritage protégé

class A { int priv ; protected : int prot ; public : int pub ; } ; class B : protected A { public : void f (void) { priv = 1 ; prot = 1 ; pub = 1 ; } } ;

class C : protected B { public : void g (void) { priv = 1 ; prot = 1 ; pub = 1 ; B b ; } } ; int main (void) { B b ; b.priv = 1 ; b.prot = 1 ; b.pub = 1 ; return 1 ; }

Remarque : même résultat avec : « class C : public B »

Page 58: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

58

Polytech Marseille , Prog. o. o. 115

L’héritage protégé

class A { int priv ; protected : int prot ; public : int pub ; } ; class B : protected A { public : void f (void) { // priv = 1 ; prot = 1 ; pub = 1 ; } } ;

class C : protected B { public : void g (void) { // priv = 1 ; prot = 1 ; pub = 1 ; B b ; } } ; int main (void) { B b ; // b.priv = 1 ; // b.prot = 1 ; // b.pub = 1 ; return 1 ; }

Polytech Marseille , Prog. o. o. 116

•  Héritage le moins restrictif et le plus utilisé

•  Utilisation : Un objet de B est vu comme « une sorte de A »

•  Tous les services offerts par a de A sont offerts par b de B. « b peut remplacer a »

L’héritage public

public

protégé

privé

Partie inaccessible héritée

protégé

privé

Partie inaccessible héritée

public

Classe de base A Classe dérivée B Obtenue par héritage public

Page 59: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

59

Polytech Marseille , Prog. o. o. 117

L’héritage public

•  Déclaration : class A { … } ; class B : public A { … } ;

•  « Aménagement » class B : public A { public :

using A::variable_protegee ; // le membre protege de A devient // public de B …

} ;

Polytech Marseille , Prog. o. o. 118

L’héritage public

class A { int priv ; protected : int prot ; public : int pub ; } ; class B : public A { public : void f (void) { priv = 1 ; prot = 1 ; pub = 1 ; } } ;

class C : public B { public : void g (void) { priv = 1 ; prot = 1 ; pub = 1 ; B b ; } } ; int main (void) { B b ; b.priv = 1 ; b.prot = 1 ; b.pub = 1 ; return 1 ; }

Page 60: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

60

Polytech Marseille , Prog. o. o. 119

L’héritage public

class C : public B { public : void g (void) { // priv = 1 ; prot = 1 ; pub = 1 ; B b ; } } ; int main (void) { B b ; //b.priv = 1 ; //b.prot = 1 ; b.pub = 1 ; return 1 ; }

class A { int priv ; protected : int prot ; public : int pub ; } ; class B : public A { public : void f (void) { // priv = 1 ; prot = 1 ; pub = 1 ; } } ;

Polytech Marseille , Prog. o. o. 120

L’héritage public

class A // solution équivalente à la précédente { int priv ; protected : int prot ; public : int pub ; A (int pri = 0, int pro = 0, int pu = 0) : priv (pri), prot (pro), pub (pu) {} A (const A & a) { priv = a.priv ; prot = a.prot ; pub = a.pub ; } } ; class B : public A { public : void f (void) { // priv = 1 ; prot = 1 ; pub = 1 ; } } ;

class C : public B { public : void g (void) { // priv = 1 ; prot = 1 ; pub = 1 ; B b ; } } ; int main (void) { B b ; // b.priv = 1 ; // b.prot = 1 ; b.pub = 1 ; return 1 ; }

Page 61: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

61

Polytech Marseille , Prog. o. o. 121

Héritage et comportement

•  Une classe B dérivant de A n’hérite pas –  des constructeurs de A (y compris de recopie) –  du destructeur de A –  de l’affectation redéfinie dans A

•  Appel récursif des constructeurs –  en partant de la racine de l’arbre d’héritage (héritage simple)

•  Appel récursif des destructeurs –  en remontant vers la racine de l’arbre d’héritage

•  Appel des constructeurs par défaut sauf précision explicite

class B : public A { public : B(…) : A(…) {…} // appel d’un constructeur de A … } ;

Attention au cas du constructeur par recopie (si défini explicitement) pour appeler le construc- teur voulu de A

Polytech Marseille , Prog. o. o. 122

Héritage et comportement

•  Un exemple d’enchaînement … { Losange los ; exécution de FigureGeometrique () Polygone () Parallelogramme () Losange () } exécution de ~Losange ()

~Parallelogramme () ~Polygone () ~FigureGeometrique ()

FigureGeometrique

Polygone Parallelogramme Triangle

Rectangle Losange

Carre

Page 62: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

62

Polytech Marseille , Prog. o. o. 123

Héritage et constructeurs

#include <iostream> class A { public : int _m ; A() {_m = 0 ; } A(const A &a) {_m = a._m ;} } ; class B : public A { }; int main(void) { B b1 ; b1._m = 1 ; B b2 = b1 ; cout << b2._m << endl ; return 1 ; }

Résultat : 1

Polytech Marseille , Prog. o. o. 124

Héritage et constructeurs

#include <iostream> using namespace std ; class A { public : int _m ; A() {_m = 0 ; } A(const A &a) {_m = a._m ;} } ; class B : public A { public : // comme un des constructeurs est précisé, il // faut les 2 car sinon erreur dans le main B() {} B(const B &b) {} }; int main(void) { B b1 ; b1._m = 1 ; B b2 = b1 ; cout << b2._m << endl ; return 1 ; }

Résultat : 0

Il faut préciser le constructeur de A à appeler

Il faut un constructeur par défaut pour A

Page 63: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

63

Polytech Marseille , Prog. o. o. 125

Héritage et constructeurs

#include <iostream> using namespace std ; class A { public : int _m; A() {_m = 0 ; } A(const A &a) {_m = a._m ;} } ; class B : public A { public : B() {} B(const B &b) : A(b) {} }; int main(void) { B b1 ; b1._m = 1 ; B b2 = b1 ; cout << b2._m << endl ; return 1 ; }

Résultat : 1

Gestion correcte des appels des constructeurs

Polytech Marseille , Prog. o. o. 126

Héritage et spécialisation

•  Redéfinition des membres

// Un exemple à ne pas suivre

int x ; // à éviter : juste ici pour l’exemple class A { public : int x ; } ;

class B : public A { public : int x ; void f (void) { x = x + 1 ; // incrémente le x de B A::x = A:: x + 1 ; // incrémente de x de A ::x = ::x + 1 ; // incrémente le x global

} } ;

Page 64: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

64

Polytech Marseille , Prog. o. o. 127

•  Redéfinition des fonctions membres

// Un exemple qui doit aussi être médité class A {

public : void f (int) ; void f (void) ;

} ;

class B : public A { public : void f (void) ; } ;

int main (void) { B b ; b.f (1) ; // illégal car les fonctions f de A sont cachées

// par celle de B b.A::f (1) ; // ok

b.f () ; // c’est la fonction f de B qui est appelée return 1 ;

}

Héritage et spécialisation

Polytech Marseille , Prog. o. o. 128

Héritage et enrichissement

•  Nouveaux membres ; nouvelles fonctions membres

class A { public : int _x ; void f (void) ; protected : int _y ; void g (void) ; } ;

class B : public A { // B hérite de _x, _y, f et g public : int _xplus ; void fplus (void) protected : int _yplus ; void gplus (void) ; } ;

Page 65: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

65

Polytech Marseille , Prog. o. o. 129

Héritage simple : un exemple (1/4)

•  Implémentation de la classe Point (version 3)

#ifndef POINT3_H #define POINT3_H // interface de la classe Point class Point { protected : float _x, _y ; public : Point(const float=0.0, const float=0.0); Point(const Point &) ; void afficher(void) ; } ; #endif

#include <iostream> #include "Point3.h" using namespace std ; Point::Point(const float r,const float t) : _x(r), _y(t) {} Point::Point(const Point & p) { _x = p._x ; _y = p._y ; } void Point::afficher(void) { cout << "les coordonnees du point sont " << _x << ", " << _y << endl ; }

Polytech Marseille , Prog. o. o. 130

Héritage simple : un exemple (2/4)

•  Implémentation de la classe Pointcolore, derivée de Point #ifndef POINTCOLORE_H #define POINTCOLORE_H #include "Point3.h" // interface de la classe Pointcolore class Pointcolore : public Point { int _couleur ; public : Pointcolore(const float = 0.0 , const float = 0.0, const int = 0 ) ; Pointcolore(const Pointcolore &) ; void afficher(void) ; } ; #endif

#include <iostream> #include "Pointcolore.h" using namespace std ; Pointcolore::Pointcolore(const float r, const float t, const int c): Point(r,t),_couleur(c) {}

Pointcolore::Pointcolore(const Pointcolore & p) { _x = p._x ; _y = p._y ; _couleur = p._couleur ; } void Pointcolore::afficher (void) { cout << "la couleur du point est " << _couleur << endl ; Point::afficher () ; }

Page 66: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

66

Polytech Marseille , Prog. o. o. 131

Héritage simple : un exemple (3/4)

•  Exécution

#include "Pointcolore.h" int main(void) { Pointcolore p(1.0,1.0, 10) ; p.afficher (); return 1 ; }

libertad:~/essai_C> ./essai_Pointcolore

la couleur du point est : 10

les coordonnees du point sont : 1, 1 libertad:~/essai_C>

Polytech Marseille , Prog. o. o. 132

Héritage simple : un exemple (4/4)

•  Autre implémentation de la classe Pointcolore

#include <iostream> #include "Pointcolore.h » using namespace std ; Pointcolore::Pointcolore(const float r , const float t, const int c) : Point(r,t), _couleur (c) {}

Pointcolore::Pointcolore(const Pointcolore & p) : Point(p) { // on indique qu’il faut utiliser le constructeur par recopie de Point // un constructeur sera de toutes les façons appelé // _x = p._x ; // _y = p._y ; _couleur = p._couleur ; } void Pointcolore::afficher (void) { cout << "la couleur du point est " << _couleur << endl ; Point::afficher () ; }

Page 67: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

67

Polytech Marseille , Prog. o. o. 133

Héritage multiple : un exemple (1/4)

•  Implémentation de la classe Couleur (version 1)

#ifndef COULEUR_H #define COULEUR_H class Couleur { protected : int _couleur ; public : Couleur(const int = 0) ; Couleur(const Couleur &) ; void afficher(void) ; } ; #endif

// implémentation de la classe couleur #include <iostream> #include "Couleur.h » using namespace std ; Couleur::Couleur(const int c) : _couleur(c) {} Couleur::Couleur(const Couleur & cc) { _couleur = cc._couleur ; } void Couleur::afficher(void) { cout << "la couleur est " << _couleur << endl ; }

Polytech Marseille , Prog. o. o. 134

Héritage multiple : un exemple (2/4)

•  Classe Pointcolore, derivée de Point et de Couleur #ifndef POINTCOLORE2_H #define POINTCOLORE2_H #include "Point3.h" #include "Couleur.h" //interface de la classe Pointcolore class Pointcolore : public Point, public Couleur { public : Pointcolore(const float = 0.0 , const float = 0.0, const int = 0 ) ; Pointcolore(const Pointcolore &) ; void afficher(void) ; } ; #endif

#include <iostream> #include "Pointcolore2.h » using namespace std ; Pointcolore::Pointcolore(const float r, const float t, const int c) : Point(r,t), Couleur(c) {}

Pointcolore::Pointcolore(const Pointcolore & p) : Point(p), Couleur(p) {} void Pointcolore::afficher(void) { Couleur::afficher() ; // ou Point::afficher() ; // this->Couleur::afficher (); // this->Point::afficher () ; }

Page 68: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

68

Polytech Marseille , Prog. o. o. 135

Héritage multiple : un exemple (3/4)

•  Exécution

•  Il y a trois fonctions afficher

(Pointcolore::afficher, Point::afficher et Couleur::afficher)

–  Il faut préciser celle utilisée –  Peut-on choisir l’une ou l’autre de façon plus transparente ?

#include "Pointcolore2.h" int main(void) { Pointcolore p(1.0,1.0, 10) ; p.afficher (); return 1 ; }

libertad:~/essai_C> ./essai_Pointcolore2

la couleur est : 10

les coordonnees du point sont : 1, 1

libertad:~/essai_C>

Polytech Marseille , Prog. o. o. 136

Héritage public et type de liaison

•  Héritage public : les objets de B sont des sortes de A

•  Un b peut remplacer un a (idem si a est d’une classe de base accessible de B)

•  Remplacement possible à travers les pointeurs et les références

•  Mais problème d’identité : « who’s who ? »

•  Première réponse –  type statique –  type dynamique –  liaison statique

Page 69: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

69

Polytech Marseille , Prog. o. o. 137

Héritage public et type de liaison

•  Type statique et type dynamique

class A {

... } ;

class B : public A {

... } ;

int main (void) { A a, *pa, a1 ; // le type statique de pa est A (défini à la compilation)

B b , * pb ; pa = &b ; // le type dynamique de pa devient B // pb = &a ; illégal dans ce sens A &ra = b ; // le type statique de ra est A (défini à la compilation)

// mais son type dynamique est B // B &rb = a ; illégal dans ce sens

pa = &a1 ; // le type dynamique de pa devient A return 1 ;

}

Polytech Marseille , Prog. o. o. 138

•  Quel membre, quelle fonction membre sont utilisés ?

Par défaut, la liaison est déterminée statiquement à la compilation et correspond donc au type statique. La liaison est statique.

•  Premier exemple

class A { public : int a; } ;

class B : public A { public : int a; } ;

Héritage public et type de liaison

using namespace std ; int main (void) { B b ; A *pa = &b ; b.A::a = 1 ; b.B::a = 2 ; int c = pa->a ; // c’est A::a qui est mis dans c A &ra = b ; int d = ra.a ; // c’est A::a qui est mis dans d cout << "c=" << c << "" "" << "d=" << d << endl ; return 1 ; }

[titaniummd:~/Desktop] mdaniel% ./test c=1d=1

Page 70: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

70

Polytech Marseille , Prog. o. o. 139

•  Deuxième exemple : les points colorés ! (essai_Pointcolore3)

Héritage public et type de liaison

#include "Pointcolore2.h" using namespace std ; int main(void) { Pointcolore p1(1.0,1.0,10) ; Point p2, *ptr3 ; Couleur *c1 ; p1.afficher () ; // impression "normale » p1.Couleur::afficher () ; // en tant qu'héritier de Couleur p1.Point::afficher () ; // en tant qu'héritier de Point p2 = p1 ; // on perd la couleur ! p2.afficher () ; ptr3 = &p2 ; ptr3->afficher () ; ptr3 = &p1 ; ptr3->afficher () ; c1 = &p1 ; c1->afficher () ; return 1 ; }

libertad~/essai_C> ./essai_Pointcolore3 la couleur est 10 les coordonnees du point sont 1, 1 la couleur est 10 les coordonnees du point sont 1, 1 les coordonnees du point sont 1, 1 les coordonnees du point sont 1, 1 les coordonnees du point sont 1, 1 la couleur est 10 libertad~/essai_C>

Polytech Marseille , Prog. o. o. 140

•  But : Utiliser la fonction membre (la donnée membre) correspondant au type dynamique

•  La fonction membre doit être définie comme virtuelle

La liaison est effectuée au moment de l’exécution. La liaison est dynamique

•  Un constructeur ne peut pas être déclaré virtual –  On est à la construction de l’objet. Seul le type statique est connu –  Aucune indirection possible

•  Un destructeur « peut » être déclaré virtual –  On a même intérêt à le déclarer virtual

•  (utilisé dans le cas du polymorphisme) •  pour détruire le bon objet pointé ou référencé en utilisant la bonne

hiérarchie de destructeurs

Héritage public et liaison dynamique

Page 71: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

71

Polytech Marseille , Prog. o. o. 141

•  Pourquoi déclarer un destructeur virtual ?

Héritage public et liaison dynamique

#include <iostream> using namespace std ; class A { public :

~A() { cout << "destructeur de A" << endl ;} } ; class B : public A { public :

int * ptrb ; B() { ptrb= new int [1000]; } ~B() { cout << "destructeur de B" << endl ; delete [] ptrb ; }

} ; int main () { A * ptr ; ptr = new B; delete ptr ; return 0 ; }

MacBook-Marc-Daniel:essai_CPP mdaniel$ g++ -o destructeurs destructeurs.cxx MacBook-Marc-Daniel:essai_CPP mdaniel$ ./destructeurs destructeur de B destructeur de A

…$ g++ -o destructeurs destructeurs.cxx …$ ./destructeurs destructeur de A …$

Polytech Marseille , Prog. o. o. 142

•  Pourquoi déclarer un destructeur virtual ?

Héritage public et liaison dynamique

#include <iostream> using namespace std ; class A { public :

virtual ~A() { cout << "destructeur de A" << endl ;} } ; class B : public A { public :

int * ptrb ; B() { ptrb= new int [1000]; } ~B() { cout << "destructeur de B" << endl ; delete [] ptrb ; }

} ; int main () { A * ptr ; ptr = new B; delete ptr ; return 0 ; }

MacBook-Marc-Daniel:essai_CPP mdaniel$ g++ -o destructeurs destructeurs.cxx MacBook-Marc-Daniel:essai_CPP mdaniel$ ./destructeurs destructeur de B destructeur de A

…$ g++ -o destructeurs destructeurs.cxx …$ ./destructeurs destructeur de B destructeur de A …$

Page 72: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

72

Polytech Marseille , Prog. o. o. 143

class FigureGeometrique { public : virtual void tracer (void) { } } ; class Polygone : public FigureGeometrique { public : virtual void tracer (void) { } } ; class Triangle : public Polygone { } ; class Ellipse : public FigureGeometrique { public : void tracer (void) { } } ; class Cercle : public Ellipse { } ; void dessiner(FigureGeometrique *figure[],int nb) { for (int i = 0 ; i < nb ; i = i + 1 ;) figure [i] ->tracer () ; // liaison dynamique }

Héritage public et liaison dynamique

int main (void) { FigureGeometrique *figure[4] ; figure [0] =new Triangle ; figure [1] =new Ellipse ; figure [2] =new Cercle ; figure [3] =new FigureGeometrique ; dessiner(figure,4) ; }

Ce n’est pas la même fonction tracer appelée à chaque fois

Polytech Marseille , Prog. o. o. 144

class FigureGeometrique { public : virtual void tracer(void) { } } ; class Polygone : public FigureGeometrique { public : virtual void tracer(void) { } } ; class Triangle : public Polygone { } ; class Ellipse : public FigureGeometrique { public : void tracer (void) { } } ; class Cercle : public Ellipse { } ; void dessiner (FigureGeometrique *figure[], int nb ) { for (int i = 0 ; i < nb ; i = i + 1 ;) figure [i] ->tracer () ; // liaison dynamique }

Héritage public et liaison dynamique

Cette fonction est virtuelle par défaut

Fonction utilisée par Triangle

Fonction utilisée par Cercle

Cette fonction est indispensable

Page 73: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

73

Polytech Marseille , Prog. o. o. 145

•  Remarque : liaison dynamique = indirection un peu plus coûteux à l’appel

•  La redéfinition d’une fonction virtuelle doit garder la même signature sinon

•  pas de redéfinition •  masquage

•  type de retour : des contraintes 1) même type de retour

Héritage public et liaison dynamique

class A { public : virtual void f(int) ; } ; class B : public A { public : virtual void f(int) ; } ;

class A { public : virtual int f(void) ; } ; class B : public A { public : virtual int f(void) ; } ;

Polytech Marseille , Prog. o. o. 146

Héritage public et liaison dynamique

class A { public : virtual A & f(void) ; } ; class B : public A { public : virtual B & f(void) ; } ;

•  type de retour : des contraintes 1) types de retour « compatibles » 2) retour d’un pointeur ou d’une référence

les types de retour sont des pointeurs ou des références vers des classes C et D où C est une classe de base accessible de D

cas général cas particulier important class C { } ; class D : public C { } ;

class A { public : virtual C & f(void) ; } ;

class B : public A { public : virtual D & f(void) ; } ;

Page 74: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

74

Polytech Marseille , Prog. o. o. 147

Héritage public et liaison dynamique : avant un exemple

•  Imaginez un jeu d’échec –  Une liste de pointeurs sur des pièces (classe Piece) –  Un ensemble de pièces spécifiques héritant publiquement de la classe

Pièce (Fou, Tour, Pion, ….) –  Chaque pièce spécifique a sa fonction déplacer –  La classe Piece a aussi une fonction deplacer (virtuelle)

•  Comment tester le déplacement de toutes les pièces de l’échiquier ?

Polytech Marseille , Prog. o. o. 148

Héritage public et liaison dynamique : un exemple

•  Classe Point (version 4) : définition de Point

#ifndef POINT4_H #define POINT4_H // interface de la classe Point class Point { protected : float _x, _y ; public : Point(const float = 0.0 , const float = 0.0 ) ; Point(const Point &) ; virtual void afficher(void); virtual ~Point(void); }; #endif

Page 75: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

75

Polytech Marseille , Prog. o. o. 149

Héritage public et liaison dynamique : un exemple

•  Classe Point (version 4) : implémentation de Point

#include <iostream> #include "Point4.h » using namespace std ; Point::Point(const float r,const float t) : _x (r), _y (t) { cout << "constructeur de Point" << endl ; } Point::Point(const Point & p) { _x = p._x ; _y = p._y; cout << "constructeur par recopie de Point" << endl ; } void Point::afficher(void) { cout << "les coordonnees du point sont " << _x << ", " << _y << endl; } Point::~Point(void) { cout << "destructeur de Point" << endl ; }

Polytech Marseille , Prog. o. o. 150

Héritage public et liaison dynamique : un exemple

•  Classe Couleur (version 2) : définition de Couleur

#ifndef COULEUR2_H #define COULEUR2_H class Couleur { protected : int _couleur ; public : Couleur(const int = 0) ; Couleur(const Couleur &) ; virtual void afficher(void) ; virtual ~Couleur(void) ; } ; #endif

Page 76: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

76

Polytech Marseille , Prog. o. o. 151

Héritage public et liaison dynamique : un exemple

•  Classe Couleur (version 2) : implémentation de Couleur

#include <iostream> #include "Couleur2.h" Couleur::Couleur(const int c) : _couleur(c) { cout << "constructeur de Couleur" << endl ; } Couleur::Couleur(const Couleur & cc) { _couleur = cc._couleur ; cout << "constructeur par recopie de Couleur" << endl ; } void Couleur::afficher(void) { cout << "la couleur est " << _couleur << endl ; } Couleur::~Couleur(void) { cout << "destructeur de Couleur" << endl ; }

Polytech Marseille , Prog. o. o. 152

Héritage public et liaison dynamique : un exemple

•  Classe Pointcolore (version 3) : définition de Pointcolore

#ifndef POINTCOLORE3_H #define POINTCOLORE3_H #include "Point4.h" #include "Couleur2.h" // interface de la classe Pointcolore class Pointcolore : public Point, public Couleur { public : Pointcolore (const float = 0.0 , const float = 0.0, const int = 0 ) ; Pointcolore (const Pointcolore &) ; virtual void afficher (void) ; virtual ~Pointcolore (void) ; } ; #endif

Page 77: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

77

Polytech Marseille , Prog. o. o. 153

Héritage public et liaison dynamique : un exemple

•  Classe Pointcolore (version 3) : implémentation de Pointcolore

#include <iostream> #include "Pointcolore3.h » using namespace std ; Pointcolore::Pointcolore(const float r, const float t, const int c) : Point(r,t), Couleur(c) { cout << "constructeur de Pointcolore" << endl ; }

Pointcolore::Pointcolore(const Pointcolore & p) : Point(p), Couleur(p) { cout << "constructeur par recopie de Pointcolore" << endl ; } void Pointcolore::afficher(void) { Couleur::afficher () ; Point::afficher () ; } Pointcolore::~Pointcolore(void) { cout << "destructeur de Pointcolore" << endl ; }

Polytech Marseille , Prog. o. o. 154

Héritage public et liaison dynamique : un exemple

•  Essai_Pointcolore4

#include <iostream> #include "Pointcolore3.h" int main(void) { Pointcolore pc (1.0,1.0,10), *ppc ; Point p, *pp ; Couleur *c ; pc.afficher(); pc.Couleur::afficher(); pc.Point::afficher() ; pp = new Pointcolore(2.0, 2.0, 5) ; pp->afficher() ; delete pp ; c = new Pointcolore(3.0, 3.0, 2) ; c->afficher(); delete c ; p = pc ; p.afficher() ; pp = &p ; pp->afficher() ; pp = &pc ; pp->afficher() ; ppc = (Pointcolore *)pp ; ppc->afficher() ; c = &pc ; c->afficher () ; return 1 ; }

constructeur de Point constructeur de Couleur constructeur de Pointcolore constructeur de Point la couleur est 10 les coordonnees du point sont 1, 1 la couleur est 10 les coordonnees du point sont 1, 1 constructeur de Point constructeur de Couleur constructeur de Pointcolore la couleur est 5 les coordonnees du point sont 2, 2 destructeur de Pointcolore destructeur de Couleur destructeur de Point constructeur de Point constructeur de Couleur constructeur de Pointcolore la couleur est 2 les coordonnees du point sont 3, 3 destructeur de Pointcolore destructeur de Couleur destructeur de Point les coordonnees du point sont 1, 1 les coordonnees du point sont 1, 1 la couleur est 10 les coordonnees du point sont 1, 1 la couleur est 10 les coordonnees du point sont 1, 1 la couleur est 10 les coordonnees du point sont 1, 1 destructeur de Point destructeur de Pointcolore destructeur de Couleur destructeur de Point

Page 78: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

78

Polytech Marseille , Prog. o. o. 155

•  C’est la possibilité de faire référence à une classe dérivée à partir d’une variable d’instance d’une classe de base (accessible)

•  On parle aussi d’affectation polymorphique

•  (voir glossaire)

•  En C++, l’affectation polymorphique passe par des pointeurs (et des références). C’est une affectation sûre.

•  Dans l’autre sens, si *pta, pointeur de type A, pointe sur un objet de type B, dérivé public de A, on peut l’affecter à un pointeur de type B. C’est l’affectation polymorphique inverse : Affectation beaucoup plus risquée

Héritage public et polymorphisme

Polytech Marseille , Prog. o. o. 156

Héritage public et polymorphisme

Transtypage ou « cast » (1/3)

•  affectation polymorphique : affectation sûre class A { virtual void f () ; … } ;

class B : public A { … } ;

int main (void) { B *b = new B ; A *a ; // tous les transtypages sont corrects : b est une sorte de A a = (A *) b ; a = b ; a = dynamic_cast <A *> (b) ; return 1 ;

}

Page 79: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

79

Polytech Marseille , Prog. o. o. 157

Transtypage ou « cast » (2/3)

•  affectation polymorphique inverse : affectation risquée class A { virtual void f () ; … } ;

class B : public A { … } ;

int main (void) { A *a = new A ; B *b ; b = (B *) a ; // inutilisable ici (et a priori) mais autorisé

// b = a ; erreur de compilation b = dynamic_cast <B *> (a) ;

// b vaut NULL ou 0 car a n’est pas une sorte de B // ce transtypage est sûr

return 1 ; }

Héritage public et polymorphisme

Polytech Marseille , Prog. o. o. 158

Transtypage ou « cast » (3/3)

•  affectation polymorphique inverse : affectation risquée class A { virtual void f () ; … } ;

class B : public A { … } ;

int main (void) { A *a = new B ; B *b ; b = (B *) a ; // OK ici, mais risqué

// b = a ; erreur de compilation b = dynamic_cast <B *> (a) ; // OK car a est en fait une sorte de B

// (ici un B) // ce transtypage est sûr

return 1 ; }

Héritage public et polymorphisme

Page 80: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

80

Polytech Marseille , Prog. o. o. 159

•  Fonctions virtuelles pures

class FigureGeometrique { public : virtual void tracer(void) = 0 ; } ; class Polygone : public FigureGeometrique { public : virtual void tracer(void) { } } ; class Triangle : public Polygone { } ; ... void dessiner(FigureGeometrique *figure[], int nb ) { for (int i = 0 ; i < nb ; i = i + 1 ;) figure [i] ->tracer () ; // liaison dynamique }

Héritage public et classes abstraites

FigureGeometrique::tracer est trop générale pour être implémentée. Elle est déclarée virtuelle pure

L’implémentation de tracer est différée et déléguée aux classes dérivées

Polytech Marseille , Prog. o. o. 160

•  Une classe est abstraite si elle ne peut pas être instanciée

–  Elle possède au moins une fonction membre virtuelle pure ou –  Tous ses constructeurs sont protégés ou privés

•  Une classe abstraite ne peut que servir de moule pour ses classes dérivées.

•  Elle ne peut pas être instanciée mais peut servir à déclarer des pointeurs … qui pointeront sur des instances d’une classe dérivée (concrète) –  Attention aux constructeurs non accessibles …. –  Elle peut être instanciée via des astuces de programmation

•  Fonction statique publique de la classe qui crée un objet et le retourne !!!!

Héritage public et classes abstraites

Page 81: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

81

Polytech Marseille , Prog. o. o. 161

•  Une classe dérivée d’une classe abstraite peut :

–  rester abstraite (héritage des fonctions virtuelles pures non redéfinies) ou –  devenir concrète (toutes les fonctions sont redéfinies)

•  Revenons sur le jeu d’échec –  Quel est le statut de la fonction déplacer de Piece ? –  Que peut-on dire de Piece ?

Héritage public et classes abstraites

Polytech Marseille , Prog. o. o. 162

•  Intérêt d’une classe abstraite :

–  expliciter tout ce qui est nécessaire pour manipuler correctement les objets

–  même si on ne sait pas encore le faire

–  tout ce que l’on sait faire peut être fait et n’est plus à faire

–  garantir que les classes dérivées concrètes définiront bien tout ce qu’il faut.

Héritage public et classes abstraites

Page 82: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

82

Polytech Marseille , Prog. o. o. 163

•  Héritage multiple à partir de deux classes « disjointes » –  pas de problème particulier –  ex : class Pointcolore : public Point, public Couleur

•  Héritage multiple à partir de deux classes ayant une classe de base commune : il ne faut pas dupliquer

Une astuce prévue en C++ (voir la doc !)

Héritage public et classes virtuelles

Parallelogramme

Rectangle Losange

Carre

Polytech Marseille , Prog. o. o. 164

La généricité et les modèles

Page 83: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

83

Polytech Marseille , Prog. o. o. 165

La généricité : les concepts

•  Voir glossaire

•  Mécanisme très abstrait, mais très performant :

on est autorisé à définir des opérations, des types, des classes de « trucs » ou de « machins ». La réalité commence à l’instanciation. Il n’y a rien à redéfinir

Ce n’est pas le même mécanisme que la redéfinition des fonctions ou opérateurs

•  Un « exemple » : fonction d’échange. On échange deux trucs

en passant par un truc intermédiaire. –  Ensuite, on peut échanger n’importe quel machin, sous réserve que

l’affectation ait été définie pour ce machin

Polytech Marseille , Prog. o. o. 166

La généricité : les concepts

•  Ce n’est pas un mécanisme de la programmation objet (sauf pour les classes génériques), mais c’est un mécanisme propre aux langages de programmation de « haut niveau »

•  Correspond bien à une volonté de réutiliser des composants

•  C’est un mécanisme statique (géré à la compilation)

•  N’offre pas de garantie contre les erreurs : –  La partie générique peut être correcte –  L’instanciation peut être erronée

•  au moment de la compilation (instanciation) •  à l’exécution si les opérations sur le type instancié sont erronées

Page 84: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

84

Polytech Marseille , Prog. o. o. 167

La généricité : modèle de fonction en C++

T est un paramètre particulier du modèle qui s’appelle paramètre type. Son argument associé sera un type. La norme autorise aussi class à la place de typename

Pas de type de retour ici

Rem : beaucoup plus performant que de surcharger les fonctions pour chaque type. Par contre, la signature est toujours la même

Retourne ici un T

•  Passe par la définition de modèles ou patrons

–  en anglais template = patron

1) Définition (sur deux exemples) template <typename T> T inf(const T a, const T b) { return (a < b ? a : b) ; } template <typename T> void swap(T &a, T &b) { T temp ; temp = a ; a = b ; b = temp ; }

Polytech Marseille , Prog. o. o. 168

2) Instanciation

–  Sous réserve : •  que l’affectation ait un sens •  que l’opérateur < ait un sens

–  Sous réserve : •  que l’affectation ait un sens •  qu’il existe un constructeur par défaut (pour temp !)

La généricité : modèle de fonction en C++

int a = …, b = …, c = inf(a,b) ; char e = …, f = …, g = inf(e,f) ;

L’argument-type est int

L’argument-type est char

int a = …, b = ... ; char e = …, f = … ; swap(a, b) ; swap(e, f) ;

Page 85: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

85

Polytech Marseille , Prog. o. o. 169

•  Il y a des contraintes : c’est à l’utilisateur de les gérer •  Cohabitation : surcharge possible pour certains types

Attention aux règles de recherche des fonctions surchargées !

La généricité : modèle de fonction en C++

template <typename T> T inf(const T a, const T b) { return (a < b ? a : b) ; } char * inf(const char * a, const char * b) { return (strcmp(a,b) < 0) ? a : b ; }

int main(void) { int i, j ; char *c ; i = inf(i, j) ; // instanciation du patron c = inf( "POLYTECH", "the best") ; // appel de la fonction pour les char * return 1 ; }

Polytech Marseille , Prog. o. o. 170

Un exemple simplifié (1/2)

La généricité : modèle de classe en C++

// définition de la classe générique template <typename Type> class Maclasse_gen { Type _v ; public : Maclasse_gen(const Type &) ; Maclasse_gen(const Maclasse_gen<Type> &) ; Type valeur (void) ; } ; // implémentation à suivre (règle) // (ou implémentation simultanée …) template <typename Type> Maclasse_gen<Type>::Maclasse_gen(const Type &v) : _v(v) {} template <typename Type> Maclasse_gen<Type>::Maclasse_gen(const Maclasse_gen<Type> &membre) { _v = membre._v ; } template <typename Type> Type Maclasse_gen<Type>::valeur (void) { return _v ; }

Page 86: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

86

Polytech Marseille , Prog. o. o. 171

Un exemple simplifié (2/2)

La généricité : modèle de classe en C++

#include <iostream> #include "gene.h » using namespace std ; int main (void) { Maclasse_gen <int> mci(12) ; Maclasse_gen <float> mcf(3.14159) ; cout << "les deux valeurs sont : " << mci.valeur() << " et " << mcf.valeur() << endl ; return 1 ; }

libertad:~/essai_C> g++ -c essai_gen.cxx libertad:~/essai_C> g++ -o essai_gen essai_gen.o libertad:~/essai_C> ./essai_gen les deux valeurs sont : 12 et 3.14159 libertad:~/essai_C>

Polytech Marseille , Prog. o. o. 172

Fonctions membres

•  déclaration et définition dans le même fichier .h –  voir aussi l’inclusion d’un fichier dans le .h (comme les fonctions inline) –  Si simultanées : fonctions inline par défaut –  Si décalées : plus lisible dans les cas réels

La généricité : modèle de classe en C++

// définition de la classe générique template <typename Type> class Maclasse_gen { Type _v ; public : Maclasse_gen (const Type &v) : _v(v) {} Maclasse_gen (const Maclasse_gen<Type> &membre) {_v = membre._v ; } Type valeur (void) { return _v ; } } ;

Page 87: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

87

Polytech Marseille , Prog. o. o. 173

Encore quelques remarques (1/3)

•  paramètres par défaut

La généricité : modèle de classe en C++

// définition de la classe tableaux génériques de taille fixe #ifndef TABGENFIXE_H #define TABGENFIXE_H template <int taille = 100, typename T = int > class TableauGeneriqueFixe { T tab[taille] ; public : … T &operator [] (const int i) { assert (i<taille); return tab [i]; } } ; #endif

… // tableau de 10 réels TableauGeneriqueFixe <10, float> tab1 ; // tableau de 10 caractères TableauGeneriqueFixe <10, char> tab2 ; // tableau de 100 entiers TableauGeneriqueFixe <> tab3 ; // TableauGeneriqueFixe tab4 erreur, < >

Polytech Marseille , Prog. o. o. 174

Encore quelques remarques (3/3)

•  Instanciation d’un paramètre-type par un type fonction

La généricité : modèle de classe en C++

#include <iostream> using namespace std ; template <typename Op, typename T> T appliquer (Op op, T x, T y) { return op (x, y) ; } float plus (float x, float y) { return x + y ; } float mult (float x, float y) { return x * y ; } ; int main (void) { float x = 1, y = 2 ; cout << appliquer (plus, x, y) << endl ; cout << appliquer (mult, x, y) << endl ; return 1 ; }

libertad:~/essai_C> ./a.out 3 2 libertad:~/essai_C>

Page 88: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

88

Polytech Marseille , Prog. o. o. 175

La gestion des exceptions

Polytech Marseille , Prog. o. o. 176

Les exceptions : généralités

•  Une exception est un signal émis par le système en cas d’erreur d’exécution –  division par 0 –  erreur d’allocation dymanique –  accès hors d’un tableau –  …

•  Le signal est ensuite gérable ou non par le langage géré ou non par le programme

Page 89: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

89

Polytech Marseille , Prog. o. o. 177

Les exceptions : généralités

•  Dans un langage sans gestion des exceptions, on peut –  ne rien gérer

•  plantage avec un message plus ou moins explicite « segmentation fault » •  erreur muette aux conséquences imprévisibles

–  essayer de tout prévoir et si possible de gérer ensuite •  récupération des types de retour (fopen, malloc, …) •  int a, b, c ; ...

if (a != 0) c = b / a ; else

?????? •  devient parfois rapidement ingérable •  amène souvent à des variables globales, des « exit » à foison, voire des goto

–  Connaissez-vous des logiciels (programmes) très connus ne gérant pas toutes les exceptions ?

Polytech Marseille , Prog. o. o. 178

Les exceptions : généralités

•  Ce n’est pas un mécanisme de la programmation objet, mais c’est un mécanisme propre aux langages de programmation de « haut niveau »

•  C’est un mécanisme dynamique (géré à l’exécution)

•  Un utilisateur d’une fonction sait ce qu’il doit faire en cas de problème, mais doit avoir l’information

•  La fonction a généralement l’information mais ne sait pas ce qu’il faut faire

•  deux attitudes non satisfaisantes de gestion des exceptions –  arrêter le programme après un message (parfois indispensable) –  code d’erreur sur chaque fonction (inefficace en pratique sur les cas

complexes)

Page 90: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

90

Polytech Marseille , Prog. o. o. 179

Les exceptions en C++

Les exceptions en C++ se gèrent T.T.C

–  Throw : lancement éventuel de l’exception

–  Try : zone d’épreuve

–  Catch : prise de contrôle en cas d’exception levée

•  et sous la forme Throw Try/Catch

Polytech Marseille , Prog. o. o. 180

Les exceptions en C++

•  Il y a les exceptions lancées automatiquement par le système

–  bad_alloc lancée par new –  out_of_range lancée par l’opérateur [], … –  overflow_error lancée par les opérations sur les nombres –  …. –  lire la doc !

–  La division par 0 n’est pas (plus) traitée comme une exception •  doit être gérée explicitement

•  Les exceptions lancées (et donc gérées) par le concepteur

Page 91: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

91

Polytech Marseille , Prog. o. o. 181

Les exceptions en C++

•  Exceptions lancées automatiquement par le système

#include <iostream> #include <exception> using namespace std ; int main (void) { float a, b, c, d ; cout << "donner a et b" << endl ; cin >> a >> b ; try { c = a * b ; // une division par 0 ne lève pas d'exception d = a / b ; } catch (const exception & e ) { cout <<"exception de la bibliotheque standard " << e.what () << endl ; } // reste que les autres exceptions ne sont absolument pas attrapées ainsi ! // catch ( ...) récupère les autres exceptions return 1 ; }

Polytech Marseille , Prog. o. o. 182

•  Exceptions lancées automatiquement par le système

#include <exception> using namespace std ; int main(void) { float a, b, c, d ; cout << "donner a et b" << endl ; cin >> a >> b ; try { c = a * b ; // une division par 0 ne lève pas d'exception d = a / b ; } catch (const exception & e ) { cout <<"exception de la bibliotheque standard " << e.what () << endl ; } // reste que les autres exceptions ne sont absolument pas attrapées ainsi // catch ( ...) récupère les autres exceptions return 1 ; }

Les exceptions en C++

Classe de base

Zone d’épreuve

Zone de récupération

Page 92: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

92

Polytech Marseille , Prog. o. o. 183

#include <iostream> #include <exception> using namespace std ; int main (void) { int a, b, c, d ; cout << "donner a et b" << endl ; cin >> a >> b ; try { c = a * b ; if (b == 0) throw "division par zero" ; d = a / b ; } catch (const exception & e ) { cout << "exception de la bibliotheque standard " << e.what () << endl ; } catch (char *msg) { cout << msg << endl ; cout << "a moi maintenant de savoir quoi faire ici" << endl ; } return 1 ; }

Les exceptions en C++

•  Gestion d’une exception : un premier exemple

libertad~/essai_C> g++ -o exception exception.cxx libertad~/essai_C> ./exception donner a et b 1 0 division par zero a moi maintenant de savoir quoi faire ici libertad~/essai_C>

Polytech Marseille , Prog. o. o. 184

Les exceptions en C++

Plus formellement (1/5)

•  throw permet de traiter –  une erreur –  une situation exceptionnelle –  ATTENTION,

•  ni une technique de programmation, ni un goto !

–  expression peut être •  un objet •  un pointeur •  une référence •  const ou non

–  expression permet d’envoyer les informations pour la gestion de l’exception

if (situation_exceptionnelle) throw expression ;

Page 93: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

93

Polytech Marseille , Prog. o. o. 185

Les exceptions en C++

Plus formellement (2/5)

•  Le bloc try permet d’identifier une zone –  où les exceptions doivent être interceptées

•  Doit nécessairement être complété par un gestionnaire d’exceptions –  constitué par au moins un gestionnaire catch

•  Un gestionnaire catch –  suit un bloc try –  un gestionnaire catch

•  Seule throw peut accéder à un gestionnaire catch –  sous réserve de passage par un bloc try

Try { … corps du bloc … } catch (declaration_parametre1) { … instructions de gestion de l’exception 1 … } catch (declaration_parametre2) { … instructions de gestion de l’exception 2 … }

Polytech Marseille , Prog. o. o. 186

Les exceptions en C++

Plus formellement (3/5)

•  Un gestionnaire catch –  a un type

–  un gestionnaire catch de type T1, const T1 , T1 &, const T1 & est compatible avec throw T2 si :

•  T1 = T2 •  T1 classe de base accessible de T2 •  T1 et T2 pointeurs et T2 peut se convertir en T1 par une conversion standard

–  le gestionnaire catch (…) gère toutes les exceptions

–  les gestionnaires catch sont essayés séquentiellement pour trouver un gestionnaire qui convient

•  l’ordre d’écriture peut ne pas être anodin •  catch (…) est le dernier

Page 94: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

94

Polytech Marseille , Prog. o. o. 187

Les exceptions en C++

Plus formellement (4/5)

•  A l’exécution : –  les blocs try sont empilés –  lors d’un throw, le contrôle est passé au catch convenant, le moins

loin dans la pile (pour un try de la pile recherche séquentielle) –  remontée de l’interruption

–  si aucun gestionnaire ne convient : le gestionnaire prédéfini terminate prend la main. Par défaut : abort

–  Le transfert d’exécution a lieu à l’instruction suivant le groupe de gestionnaires contenant le gestionnaire activé

catch (type paramètre) { …. throw ; }

Gestionnaire sélectionné

Exécution des instructions Remontée de l’exception dans la pile

Polytech Marseille , Prog. o. o. 188

Les exceptions en C++

Plus formellement (5/5)

... void f(void ) { A aa ; if (….) throw aa ; } int main(void) { … try { f() ; } catch (A a) { … } catch (…) { … } ... return 1 ; }

Page 95: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

95

Polytech Marseille , Prog. o. o. 189

Les exceptions en C++

•  Précision des exceptions lancées ou propagées –  dans l’entête et le prototype de la fonction (la norme) :

void f( ….) throw (A, B*) ;

// ne peut lancer que des exceptions de type :

// A ou de classe accessible A

// B* ou d’un type pointeur vers un type ayant B

// comme classe accessible

// et ensuite :

void f(…..) throw(A, B*) {}

void f (…) throw ( ) ;

// aucune exception ne peut être lancée

–  à réfléchir dans le cadre de la lisibilité

Polytech Marseille , Prog. o. o. 190

•  Méthodologie de gestion des exceptions –  définir une classe de base d’exceptions (pouvant dériver de « exception »)

–  définir une hiérarchie (dérivée publiquement) d’exceptions plus spécifiques •  en enrichissant les classes dérivées pour un traitement plus « pointu » •  avec des fonctions de traitement virtuelles

–  utiliser ensuite les gestionnaires au niveau souhaité en utilisant la propriété : un gestionnaire catch de type T1, const T1 , T1 &, const T1 & est compatible avec throw T2 si :

T1 classe de base accessible de T2

–  éventuellement tout capturer avec la classe racine –  récupérer avec le bloc catch

•  un objet : pas de polymorphisme •  une référence : polymorphisme

Les exceptions en C++

Page 96: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

96

Polytech Marseille , Prog. o. o. 191

•  Méthodologie de gestion des exceptions : exemple (1/6)

Les exceptions en C++

#ifndef MES_EXCEPTIONS_H #define MES_EXCEPTIONS_H #include <iostream> #include <string> // classe de base pour le traitement de toutes // les exceptions au niveau élémentaire class MesExceptions { protected : string _libelle ; public : MesExceptions (const string & message) : _libelle (message) {} virtual ostream & afficher_exception (ostream & out = cout) const { return(out << _libelle << endl) ; } } ; // la suite page suivante

Polytech Marseille , Prog. o. o. 192

•  Méthodologie de gestion des exceptions : exemple (2/6)

–  on peut aussi rajouter public exception •  on récupère en particulier la fonction membre what() quitte à utiliser le

polymorphisme

Les exceptions en C++

// une classe pour gérer les exceptions sur le vecteur class MesExceptions_vector : public MesExceptions { protected : int _pos, _size ; public : MesExceptions_vector(const string & message, const int i, const int j) : MesExceptions (message), _pos (i), _size (j) {} virtual ostream & afficher_exception (ostream & out = cout) const { out << _libelle << " : acces a la position " << _pos << " alors que taille = " << _size << endl ; return out ; } } ; #endif // fin du fichier

Page 97: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

97

Polytech Marseille , Prog. o. o. 193

•  Méthodologie de gestion des exceptions : exemple (3/6)

Les exceptions en C++

#include <iostream> #include "Vector.h" #include "MesExceptions.h » … // récupération de l’élément à la position pos. int Vector::get_item (const int pos) throw (Mesexceptions) { if (pos >= _size) // accès au delà du dernier élément du vecteur { throw MesExceptions_vector("dans get_item", pos, _size) ; // il n ’y a pas eu d’objet local de type MesExceptions_vector // qui aurait été détruit à la fin de get_item et qui était de // toutes les façons inutilisable à part pour le « throw » } return _array[pos] ; } …

Polytech Marseille , Prog. o. o. 194

•  Méthodologie de gestion des exceptions : exemple (4/6)

Les exceptions en C++

#include "Vector.h" #include "MesExceptions.h" using namespace std ; int main (void) { try { Vector v1(10) ; v1.get_item(13) ; } // solution 1 : la plus rustique et pas de polymorphisme // exception attrapée au niveau de MesExceptions catch (MesExceptions exception) { exception.afficher_exception (cout) ; } catch (...) { cout << "une exception pas prévue : desole" << endl ; } return 1 ; }

Page 98: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

98

Polytech Marseille , Prog. o. o. 195

•  Méthodologie de gestion des exceptions : exemple (5/6)

Les exceptions en C++

#include "Vector.h" #include "MesExceptions.h" using namespace std ; int main (void) { try { Vector v1(10) ; v1.get_item(13) ; } // solution 2 : pas de polymorphisme // exception attrapée au niveau de MesExceptions // ou au niveau de MesExceptions_vector // attention à l’ordre des blocs catch !!! catch(MesExceptions_vector exception) { exception.afficher_exception (cout) ; } catch (MesExceptions exception){ exception.afficher_exception (cout) ; } catch (...) { cout << "une exception pas prévue : desole" << endl ; } return 1 ; }

Polytech Marseille , Prog. o. o. 196

•  Méthodologie de gestion des exceptions : exemple (6/6)

Les exceptions en C++

#include "Vector.h" #include "MesExceptions.h" using namespace std ; int main (void) { try { Vector v1(10) ; v1.get_item(13) ; } // solution 3 : polymorphisme catch (MesExceptions & exception) { exception.afficher_exception (cout) ; } catch (...) { cout << "une exception pas prévue : desole" << endl ; } // l’utilisation de pointeurs est aussi possible en // envoyant dans get_item un MesExceptions_vector * // mais ne permet plus le choix de la gestion au niveau // des blocs catch return 1 ; }

Page 99: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

99

Polytech Marseille , Prog. o. o. 197

Quelques compléments

Polytech Marseille , Prog. o. o. 198

La norme C++

•  Il s’agit de la norme iso/iec 14882 : 1998 amendée en 03 –  International Standard Organisation (http://www.iso.ch) –  International Electronic Commission –  Version initiale : 748 pages ….

•  Nouvelle norme en 2011 (C++11) (voir plus loin) –  quelques amendements en 2014

•  Norme très complète et précise –  nécessite un véritable travail de recherche pour suivre précisément la

norme •  les compilateurs sont généralement plus souples que la norme •  à gérer en fonction du contexte de programmation •  surtout prendre des règles strictes cohérentes et s’y tenir

•  ATTENTION à la permissivité de certains compilateurs

Page 100: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

100

Polytech Marseille , Prog. o. o. 199

Espaces de noms

•  Fonctionnalité liée à la normalisation –  (attention à l’implémentation sur le compilateur utilisé)

Rappel : portée et visibilité •  Région déclarative : portion de programme contiguë

maximale dans laquelle les identificateurs déclarés sont a priori valides (ex : bloc { }, un programme, une classe, une fonction )

•  Voir le cas particulier de la stl (Standard Template Library) dont tous les composants se trouve dans l’espace de nom std (standard)

Polytech Marseille , Prog. o. o. 200

Espaces de noms

•  Portée d’un identificateur : partie de programme dans laquelle il est possible d’accéder à l’objet représenté par l’identificateur

•  visibilité d’un identificateur : partie de programme dans laquelle il est possible d’accéder à l’identificateur

•  visibilité = portée sauf masquage (la visibilité est alors incluse dans la portée)

•  opérateur de résolution de portée : portee::identificateur (un identificateur particulier) ::identificateur (identificateur global)

Page 101: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

101

Polytech Marseille , Prog. o. o. 201

Espaces de noms

•  Espace de noms : région déclarative dont le nom peut être utilisé pour accéder aux identificateurs qui y sont déclarés (ce sont des membres de l’espace de noms)

•  intérêt : gestion des conflits de noms dans les cas complexes –  utilisation de plusieurs bibliothèques en évitant les collisions

d’identificateurs –  sélection d’un identificateur

namespace N { int i, j ; void f ( ) { … } class C { … } ; … }

C’est une extension du contexte précédent : il n’y avait pas d’espace nommé, mais un espace global

Polytech Marseille , Prog. o. o. 202

Espaces de noms

•  Un exemple illustratif (mais non exhaustif …)

namespace N { int i, j ; void f ( ) { … } class C { … } ; … namespace M { void g ( void) { f ( ) ; } } } namespace O { int j ; void h () { j = 0 ; // i = 0 ; non N::i = 0 // oui // f ( ) ; non N::f ( ) ; oui } }

// la suite N::C c ; // nouvel objet int main (void) { N::i = 0 ; N::f () ; // N::g () ; non N::M::g () ; // oui !! return 1 ; }

Page 102: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

102

Polytech Marseille , Prog. o. o. 203

•  Déclaration using : using region::identificateur ;

–  introduit identificateur de region dans la région courante –  attention au masquage

Espaces de noms

namespace N { int i, j ; void f ( ) { … } … } namespace O { int j ; void h () { using N::f ; j = 0 ; // i = 0 ; non N::i = 0 // oui f ( ) ; oui N::f ( ) ; oui } }

Polytech Marseille , Prog. o. o. 204

Espaces de noms

namespace N { int i, j ; void f (void) { … } class C { … } ; … namespace M { void g (void) { f ( ) ; } } }

// la suite using namespace N ; C c ; // nouvel objet int main (void) { i = 0 ; f () ; // g () ; non M::g () ; // oui !! return 1 ; }

•  Directive using : using namespace nom_espace ; –  introduit tous les identificateurs de nom_espace dans la région courante –  si ambiguïté entre deux identificateurs --> il faut spécifier

•  Définition d’un alias : namespace N = le_nom_donne_initialement_a_cet_espace_de_nom ;

Page 103: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

103

Polytech Marseille , Prog. o. o. 205

Amitiés, Héritage et membres statiques

•  « L’amitié ne se transfère pas par héritage »

•  Les membres statiques sont partagés avec les objets dérivés

Un peu de pratique : Amitié, Héritage et Généricité

class A { public : friend void f (void) ; int i ; } ; class B : private A { int j ; } ; void f (void) { B b ; b.i = 1 ; // oui, car hérite de A // b.j = 1 ; non, car propre à B

A rapprocher de « les amis de mes amis ne sont pas mes amis »

Polytech Marseille , Prog. o. o. 206

Amitiés, Généricité et membres statiques

•  « Les amis de mon patron sont mes amis »

–  Chaque instance conserve la fonction ou la classe amie du modèle

•  Chaque instance a son propre jeu de membres statiques

Un peu de pratique : Amitié, Héritage et Généricité

Page 104: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

104

Polytech Marseille , Prog. o. o. 207

Les composants prédéfinis STL (Standard Template Library)

Polytech Marseille , Prog. o. o. 208

La norme d’utilisation (1/2)

•  La STL ( Standard Template Library ) définit un ensemble de classes d'usage général dont l'interface est standardisée. –  Les éléments sont déclarés dans l'espace de nom std ("standard")

–  Il faut utiliser l’espace de noms std

#include <iostream> #include <string> int main(void) { int cout = 1 ; std::string s="c'est la norme" ; //std::cout << "cela marche" << " " << s << endl ; std::cout << "cela marche" << " " << s << std::endl ; std::cout << "cout=" << cout << std::endl ; return 1 ; }

[titaniummd:~/Desktop] mdaniel% ./norme cela marche c'est la norme cout=1

Page 105: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

105

Polytech Marseille , Prog. o. o. 209

La norme d’utilisation (2/2)

•  A l’intérieur d’un main on peut inclure l’espace de noms std pour simplifier l’écriture

–  Il faut utiliser l’espace de noms std

#include <iostream> #include <string> using namespace std ; int main(void) { //int cout = 1 ; string s="c'est la norme" ; cout << "cela marche" << " " << s << endl ; std::cout << "cela marche aussi" << " " << s << endl ; return 1 ; }

[titaniummd:~/Desktop] mdaniel% ./norme2 cela marche c'est la norme cela marche aussi c'est la norme

Polytech Marseille , Prog. o. o. 210

•  Schéma d’héritage des flux d’E/S

extraction ou injection d’informations formatées ou non lire la documentation !

Les flux d’E/S

ios_base basic_ios

istream

ostream

istringstream

ifstream

ostringstream

ofstream

Page 106: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

106

Polytech Marseille , Prog. o. o. 211

•  Création des flux (avec ou sans connexion à un nom) •  Connexion d’un flux avec un nom •  Test d’ouverture (gestion des erreurs) •  Gestion des états (hérité de basic_ios)

–  ex : cin.good() retourne vrai si pas d’indicateur d’erreur positionné •  Fermeture •  Opérateurs << et >> •  Extraction d’un caractère, d’une ligne, de n octets •  Insertion d’un caractère, de n octets, vidage du tampon de

sortie •  Gestion de flux en mémoire tampon : conversions, ...

•  Il y a 4 flux prédéfinis –  cin, cout, cerr, clog –  peuvent être redirigés : cela dépend du système utilisé

Les flux d’E/S

Polytech Marseille , Prog. o. o. 212

Entrées sorties formatées •  gérées par des indicateurs de ios_base

–  manipulables par des fonctions membres de la classe

•  ou avec des manipulateurs prédéfinis de l’état du flux –  le plus connu : endl –  inséré en tant qu’opération modifiant l’état du flux

•  cout << dec << i << hex << j ; // i en décimal, j en hexadécimal •  uppercase, lowercase, •  left , right // justifié à gauche, à droite (voir setw()) •  fixed, scientific // dddd.ddd ou d.ddddEdd •  ….

–  avec paramètres (sous réserve d’inclure <iomanip>) •  setprecision(5) // 5 chiffres après le point pour les flottants •  setw(n) // le champ suivant occupe n positions

•  ou avec des manipulateurs définis par l’utilisateur …

Les flux d’E/S

Page 107: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

107

Polytech Marseille , Prog. o. o. 213

Entrées sorties formatées : un exemple Les flux d’E/S

#include <iostream> #include <iomanip> using namespace std ; int main(void) { float f1=0.1234567 ; float f2=0.123456789 ; cout << "f1 =" <<f1 << "----" <<"f2=" <<f2 << endl ; cout << "f1 =" << setprecision(7) <<f1 << "----" <<"f2=" << setprecision(10) <<f2 << endl; f1= f1*1.0e-7 ; f2=f2*1.0e-7 ; cout << fixed ; cout << "f1 =" << setprecision(7) <<f1 << "----" <<"f2=" << setprecision(10) <<f2 << endl ; cout << scientific ; cout << "f1 =" << setprecision(7) <<f1 << "----" <<"f2=" << setprecision(10) <<f2 << endl; return 0 ; } // attention, les chiffres affichés ici sont juste pour illustrer // ne pas oublier que le type float ne peut avoir qu’au plus 7 chiffres valides /* f1 =0.123457----f2=0.123457 f1 =0.1234567----f2=0.123456791 f1 =0.0000000----f2=0.0000000123 f1 =1.2345670e-08----f2=1.2345679146e-08 */

Polytech Marseille , Prog. o. o. 214

Exemples E/S avec des fichiers

Les flux d’E/S

#include <fstream> Using namespace std ; int main (void) { // création du flux et connexion automatique ifstream f_in ("file_in.dat") ; // " » ofstream f_out ("file_out.dat") ; // if (! f_in.is_open()) throw ….. Problème d’ouverture // if (! f_out.is_open()) throw ….. Problème d’ouverture int a, b ; char texte[80] ; f_in >> texte >> a >> b ; f_out << texte << endl << a << b << endl ; f_in.close () ; f_out.close () ; return 1 ; }

mon_fichier 10 15

File_in.dat

mon_fichier 1015

File_out.dat

Page 108: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

108

Polytech Marseille , Prog. o. o. 215

Exemples E/S avec des fichiers

Les flux d’E/S

#include <fstream> int main (void) { ifstream f_in ("file_in.dat") ; ofstream f_out ("file_out.dat ») if (! f_in.is_open()) // throw ….. Problème d’ouverture if (! f_out.is_open()) // throw ….. Problème d’ouverture int a, b ; char texte[132]; // au plus 132 caractères lus arrêt sur \n par défaut f_in.getline(texte,132) ; f_in >> a >> b ; f_out << texte << endl << a << b << endl ; f_in.close () ; f_out.close () ; return 1 ; }

mon debut de fichier 10 15

File_in.dat

mon debut de fichier 1015

File_out.dat

Polytech Marseille , Prog. o. o. 216

La classe String

•  Manipuler facilement les chaînes de caractères et oublier les complications du C –  un tableau de char terminé par \0 a été hérité du C !

–  La classe string est un conteneur particulier •  qui peut être manipulé par les itérateurs classiques (voir plus loin) •  les principaux outils sont spécifiques à la classe (performance)

#include <string> #include <iostream> string s1 = «Hello » ; string s2 = «the world» ; void clin-œil() { string s3 = s1 + s2 ; cout << s3 << endl ; }

Page 109: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

109

Polytech Marseille , Prog. o. o. 217

La classe String

•  Une string est une suite de caractères numérotés –  de 0 à lenght()-1 (ou de size()-1 // synonyme)

•  De nombreux constructeurs

#include <string> string s0 ; string s0bis = «» ; string s1(4, ’z’) ; // s1 vaut «zzzz» string s2 = «ESIL» ; string s3 = s2 ; string s4(s2, 1, 2) ; // s4 vaut «SI» string s5(s2+2, 2) ; // s5 vaut «IL» … // par contre // string s1 = ’z’ ; est incorrect (pas de conversion) // (correct pour l’affectation) // string s1 = 41 ; est incorrect (pas de conversion)

Polytech Marseille , Prog. o. o. 218

La classe String

•  Quelques fonctions membres –  operator [] (défini avec retour de référence) (retourne un char) –  at() idem [] mais lance out_of_range en cas d’erreur

–  operator= (avec une string ou un char) –  copy –  substr –  compare –  swap –  append –  insert –  replace –  remove –  empty –  toutes les fonctions de recherche dans la chaîne

•  find, rfind, find_first_of, find_last_of, …...

Page 110: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

110

Polytech Marseille , Prog. o. o. 219

La classe String

•  Quelques fonctions non membres –  operator + (retourne un string)

•  concatène deux strings ou un string et un char (dans n’importe quel ordre)

–  les opérateurs de comparaison •  ==, !=, <, >, <=, >=

–  istream & operator>>(istream & flot, string & str) ; –  ostream & operator<<(ostream & flot, const string & str) ;

–  istream &getline(istream & flot, string & str, char delimit = ’z’) ; •  delimit est retiré du flux, mais n’est pas mis dans str

Polytech Marseille , Prog. o. o. 220

Des String et des conversions

•  On peut avoir besoin de convertir –  Des nombres en caractères –  Ou l’inverse –  On peut créer des flux associés à des chaînes de caractères –  Un exemple :

#include <iostream> #include <sstream> using namespace std ; int main (void) { ostringstream sout; string s1("nom"),s2,s3 ; int i=1 ; sout << i ; s2=sout.str(); // recupère le contenu du flux s3=s1+s2 ; cout << s3 << endl ; return 1 ; }

mdaniel$ ./conversion nom1

Page 111: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

111

Polytech Marseille , Prog. o. o. 221

Les conteneurs- les itérateurs : introduction

•  Les conteneurs –  Objets permettant d’entreposer d’autres objets –  Permettant d’effectuer sur la collection d’objets ou sur les objets des

traitements spécifiques –  Comme tout objet, un conteneur a des méthodes –  Pour travailler sur la collection d’objet, l’outil naturel est l’itérateur

•  C’est un objet qui permet d’atteindre les objets du conteneur •  Il a des méthodes associées •  Il sait se comporter comme un indice •  Mais aussi de façon éventuellement sophistiquée •  Un itérateur « pointe » sur un objet du conteneur : il généralise la notion de

pointeur

Polytech Marseille , Prog. o. o. 222

Les conteneurs

•  Trois ingrédients pour un conteneur –  la séquence (comment on accède au conteneur) –  les types abstraits

•  construits au dessus du conteneur, ils transforment et/ou limitent les opérations applicables au conteneur

–  les conteneurs associatifs •  associe une clé aux éléments du conteneur •  la recherche s’effectue sur la clé

•  Le choix du conteneur dépend essentiellement des performances –  en fonction du traitement voulu : généralement un compromis

•  ex : insérer un élément entre deux autres

Page 112: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

112

Polytech Marseille , Prog. o. o. 223

Les conteneurs

•  Les séquences (toutes génériques de paramètre type T) –  vector : séquence à utiliser par défaut

•  accès direct •  ajout et suppression en temps constant en fin (comprendre : ne dépend pas

du nombre d’éléments) •  insertion et suppression autrement en temps linéaire

–  list •  accès séquentiel •  insertion et suppression en tout point en temps constant (à l’accès près)

–  deque •  accès direct •  ajout et suppression en temps constant en début et fin •  insertion et suppression au milieu en temps linéaire

#include <vector> #include <list> list<float> ma_liste(10) ; vector<int> v(30) ;

Polytech Marseille , Prog. o. o. 224

Les conteneurs

•  Les types abstraits (queue, priority_queue, stack) –  queue : accès limité en début et fin du conteneur sous-jacent

•  queue<list<float> > ma_liste_bridee ;

–  priority_queue : manipule des objets de type T dans un conteneur (par défaut vector) et les range en fonction d’une relation d’ordre (par défaut <)

•  « insertion en queue, suppression au début » •  Passe par l’utilisation de classe-fonctions (voir le header <functional>) pour

avoir accès à des fonctions greater, less greater_equal, ….. •  lire la doc ! •  priority_queue<vector<int>,greater_equal<int> > ma-priority-queue ;

–  stack : définit une structure de pile sur le conteneur sous-jacent •  opérations limitées aux opérations sur les piles •  stack<vector<float> > ma_pile_sur_vecteur ; •  stack<list<float> > ma_pile_sur_liste ;

Page 113: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

113

Polytech Marseille , Prog. o. o. 225

Les conteneurs

•  Les conteneurs associatifs –  rechercher les éléments mémorisés à partir d’une clé –  une relation de comparaison permettant de comparer toutes les clés (par

défaut <) et de classer (en interne) les éléments –  Comparaison à partir des fonctions de <functional>

–  quand l’élément mémorisé = clé •  set : chaque clé est unique •  multiset : les clés peuvent être dupliquées

–  quand l’élément mémorisé ≠ clé •  on sauvegarde des éléments de type T et des clés de type Key •  map : chaque clé est unique

–  map<string, int,greater<string> > mon_annuaire-tel ; // n° classés par ordre alpha des contacts

–  map<int,string> mon_annuaire-tel-inverse ;

•  multimap : les clés peuvent être dupliquées –  multimap<int,string> age-de-mes-amies ;

Polytech Marseille , Prog. o. o. 226

Les conteneurs

•  On peut faire des choses simples avec un vecteur #include <iostream> #include <vector> using namespace std ; int main (void) { vector<int> v(10) ; for (int i=0; i<5;i=i+1) v[i]=i ; for (int i= 0 ; i< 5; i=i+1) cout << v[i] << " " ; return 0 ; /* $ ./it1 0 1 2 3 4 */

Page 114: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

114

Polytech Marseille , Prog. o. o. 227

Les conteneurs

•  Mais on peut faire des traitements beaucoup plus complexes avec un vecteur –  Avec ou sans itérateurs –  Fonctions membres

•  assign(…) (plusieurs solutions suivant les paramètres) •  clear() •  push_back(…) (insère à la fin) •  pop_back(…) (supprime le dernier élément) •  insert(…) (plusieurs solutions suivant les paramètres) •  erase(…) (plusieurs solutions suivant les paramètres) •  retourner une référence sur premier élement (front) le

dernier (back) •  …

Polytech Marseille , Prog. o. o. 228

Les conteneurs

•  Un peu plus compliqué avec un vecteur #include <iostream> #include <vector> using namespace std ; int main (void) { vector<int> v(10) ; for (int i=0 ; i<5 ; i=i+1) v.push_back(i) ; // insère à la fin de v, ce qui augmente la taille for (int i= 0 ; i< v.size(); i=i+1) // v.size() est convertie en int cout << v[i] << " " ; return 0 ; /* $ ./it2 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 $ */

#include <iostream> #include <vector> using namespace std ; int main (void) { vector<int> v ; for (int i=0 ; i<5 ; i=i+1) v.push_back(i) ; // insère à la fin de v, ce qui définit la taille for (int i= 0 ; i< v.size(); i=i+1) // v.size() est convertie en int cout << v[i] << " " ; return 0 ; /* $ ./it2 0 1 2 3 4 $ */

Page 115: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

115

Polytech Marseille , Prog. o. o. 229

Les conteneurs

•  Une pile

#include <iostream> #include <stack> using namespace std ; int main (void) { stack<int> p ; // le conteneur sous-jacent est deque par défaut cout << "empty ? " << p.empty() << endl ; for (int i=0 ; i<5 ; i = i+1) p.push(i) ; cout << "nombre d'elements = " << p.size() << endl ; cout << "empty ? " << p.empty() << endl ; while(p.empty()!=true) { cout << p.top() << " " ; p.pop() ; // pop ne retourne rien } cout << endl ; return 1 ; }

$ ./cont empty ? 1 nombre d'elements = 5 empty ? 0 4 3 2 1 0 $

Polytech Marseille , Prog. o. o. 230

Les itérateurs

•  Permettent d’effectuer des opérations sur les conteneurs –  <iterator> : classe de définition –  Un itérateur est associé à un conteneur –  Certaines fonctions membres du conteneur retourne un itérateur

•  Ex : begin(), end() …

–  *iterateur : retourne l’élément courant « pointé » (généralisation du pointeur)

•  Il existe différents types d’itérateurs –  input, output –  forward, reverse –  bidirectional –  random_access

Page 116: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

116

Polytech Marseille , Prog. o. o. 231

Les itérateurs

•  Le type de l’itérateur (I) est lié au conteneur –  Output : ne peut aller qu’en avant et peut recevoir des valeurs

•  *I=V (V=*I impossible) –  Input : ne peut aller qu’en avant et permet de consulter des valeurs

•  V=*I (*I=V impossible)

–  Forward : input et output, ne peut aller qu’en avant –  Bidirectional : peut aller dans les deux sens. Associé à list, set,

multiset, map, multimap –  Random_access : peut aller dans les deux sens et accès direct via

I[indice]. Associé à vector, deque, string, array –  D’autres spécificités décrites dans la documentation …

•  Les opérations sur les itérateurs dépendent des types –  ==, !=, affectés (=), incrémentés (++) (I++ ou ++I) –  décrémentés (--) : bidirectional, random_access (I-- ou --I) –  [ ], <, >, décalage d’une valeur entière : random_access –  Il est conseillé d’étudier la documentation

Polytech Marseille , Prog. o. o. 232

Les itérateurs : un exemple

#include <vector> #include <iterator> using namespace std ; int main (void) { vector<int> v ; vector<int>::iterator itv ; vector<int>::reverse_iterator reverse_itv; for (int i=0 ; i<5 ; i = i+1) v.push_back(i) ; // remplissage du vecteur : ce n'est pas la seule méthode cout << "v.size()=" << v.size() << " " ; for (itv=v.begin(); itv!=v.end(); itv++) cout << *itv << " " ; // affichage dans un sens : méthode 1 cout << endl << "v.size()=" << v.size() << " " ; for (reverse_itv = v.rbegin(); reverse_itv!=v.rend(); reverse_itv++) cout << *reverse_itv << " " ; // affichage dans l’autre sens : méthode 1 cout << endl ; v.pop_back() ; // un élément de moins // sur un vecteur, l'itérateur est random_access // donc bidirectionnel et accès avec[ ] cout << "v.size()=" << v.size() << " " ; itv=v.begin() ; for (int i=0 ; i<v.size() ; i=i+1) cout << itv[i] << " " ; // affichage dans un sens : méthode 2 cout << endl << "v.size()=" << v.size() << " " ; itv=v.begin() ; for (int i=v.size()-1; i>=0 ; i=i-1) cout << itv[i] << " " ; // affichage dans un sens : méthode 2 cout << endl ; cout << "remarque, itv[v.size()] = " << itv[v.size()] << endl ; return 1; }

$ ./it3 v.size()=5 0 1 2 3 4 v.size()=5 4 3 2 1 0 v.size()=4 0 1 2 3 v.size()=4 3 2 1 0 remarque, itv[v.size()] = 4 $

Page 117: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

117

Polytech Marseille , Prog. o. o. 233

Les itérateurs : un autre exemple #include <iostream> #include <list> #include <iterator> using namespace std ; int main (void) { list<int> l ; for (int i=0 ; i<5 ; i = i+1) l.push_back(i) ; cout << "nombre d'elements = " << l.size() << endl ; list<int>::iterator itl ; // < n'est pas disponible sur itl for (itl=l.begin(); itl != l.end(); itl++) cout << *itl << " " ; cout << endl ; // attention sur une liste ce qui suit est impossible (les -1) // for (itl=l.end()-1; itl != l.begin()-1; itl--) list<int>::reverse_iterator reverse_itl ; for (reverse_itl=l.rbegin() ; reverse_itl!=l.rend(); reverse_itl++) cout << *reverse_itl << " " ; cout << endl ; l.pop_back() ; cout << "nombre d'elements = " << l.size() << endl ; l.front() =-1 ; // -1 en tête de liste l.insert(l.begin(),-2) ; // -2 devant -1 (le premier) for (itl=l.begin(); itl != l.end(); itl++) cout << *itl << " " ; cout << endl ; itl=l.end(); // itl "pointe" "au delà du dernier" itl--; // itl "pointe" sur le dernier" itl--; // itl "pointe" avant le dernier l.insert(itl,9) ; // insert 9 avant le précédent du dernier for (itl=l.begin(); itl != l.end(); itl++) cout << *itl << " " ; cout << endl ; l.sort() ; // trie la liste par ordre croissant for (itl=l.begin(); itl != l.end(); itl++) cout << *itl << " " ; cout << endl ; return 1 ; }

$ ./it4 nombre d'elements = 5 0 1 2 3 4 4 3 2 1 0 nombre d'elements = 4 -2 -1 1 2 3 -2 -1 1 9 2 3 -2 -1 1 2 3 9 $

Polytech Marseille , Prog. o. o. 234

Les algorithmes

•  Réalisent des traitements algorithmiques sur les conteneurs –  <algorithm> –  60 fonctions –  effectué sur l’intervalle défini par deux itérateurs first, last

•  Recherche ou comparaison –  find(), count(), equal(), mismatch(), ...

•  Modification –  fill(), remove(), swap(), replace(), ...

•  Tri

•  Recherche d’extremum

•  ...

vector<int> v(10) ; // recherche de la valeur 5 find(v.begin(), v.end(), 5) ; // ou plus utile vector<int>::iterator p = find(v.begin(), v.end(), 5) ;

Page 118: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

118

Polytech Marseille , Prog. o. o. 235

Les traitements numériques

•  On trouve les fonctions de la bibliothèque mathématique standard <cmath> et <math.h>

•  Le type valarray (générique) –  vecteur spécialisé et optimisé sur les types numériques

•  int, float, double •  une vision optimisée de vector compte tenu des éléments manipulés

–  fonctions membres applicables sur tous les éléments –  …

•  La classe complexe (générique)

•  Des algorithmes numériques (<numeric>) –  accumulate(), inner_product() –  partial_sum(), partial_difference()

•  Lire la doc !

Polytech Marseille , Prog. o. o. 236

Au sujet de la norme C++11

Page 119: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

119

Polytech Marseille , Prog. o. o. 237

C++11

•  Un certain nombre de possibilités pour « faciliter » la vie des programmeurs –  A priori encore « largement » compatible avec la norme précédente –  Attention au compilateur utilisé

•  Supporte la norme 2011 •  Permissivité permanente des compilateurs

•  Un certain nombre de possibilités dont certaines ne peuvent être acquises que si le besoin est réel –  Lire la doc !

•  C++14 : pas grand chose –  C++17 devrait voir le jour

•  S’utilise avec l’option -std=c++11

Polytech Marseille , Prog. o. o. 238

Les threads

•  Mécanisme de programmation –  Lancement de plusieurs tâches en parallèle –  Permettant du parallélisme sur une machine multiprocesseurs

•  À gérer …

–  Autrement : partage du temps entre les tâches •  Illusion de parallélisme •  Mécanismes d’échanges, de synchronisation et d’exclusion mutuelle prévus

•  A utiliser en cas de besoin réel –  Lire la doc ! –  Evidemment moins performant qu’une seule tâche

•  Mais de vraies applications

Page 120: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

120

Polytech Marseille , Prog. o. o. 239

Initialisations

•  Initialisation de variables non constantes non statiques –  en dehors d’un constructeur

–  Une donnée membre statique constante peut être initialisée ainsi

#include <iostream> using namespace std ; class Bidon { public : Bidon(){} int n=5 ; } ; int main() { Bidon b ; cout << "donnee membre non constante initialisée hors du constructeur = " << b.n << endl ; return 0 ; } /* mdaniel$ g++ -o tropcool tropcool.cxx -std=c++11 mdaniel$ ./tropcool donnee membre non constante initialisée hors du constructeur = 5 */

Polytech Marseille , Prog. o. o. 240

Initialisations : constructeurs

•  Un constructeur en appelle un autre #include <iostream>

using namespace std ; class Bidon { public : int m ; int n=5 ; float x,y; Bidon(const int d=0): m(d) {cout << "le constructeur qui initialise m" << endl ;} Bidon( float dx,float dy) : Bidon(1) { cout << "l'autre constructeur" << endl ; x=dx ; y=dy ;} // Bidon( float dx,float dy) : Bidon(1),x(dx),y(dy) {} // pas autorisé : Bidon(1) seulement // ATTENTION, il faut tout de même qu'il n'y ait aucune ambiguïté // dans les appels des constructeurs ! } ; int main() { Bidon b(0) ; cout << "*************" << endl ; Bidon b1(1.1,1.1) ; cout << "donnees membre de b1 = " << b1.m << " " << b1.x << " " << b1.y << endl ; return 0 ; } /* mdaniel$ ./tropcool3 le constructeur qui initiale m ************* le constructeur qui initiale m l'autre constructeur donnees membre de b1 = 1 1.1 1.1 */

Page 121: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

121

Polytech Marseille , Prog. o. o. 241

Fonctions virtuelles

•  Un outil de sécurisation class A {

virtual void f(); virtual void g() const; virtual void h(char); void k(); }; class B : public A { void f(); // il s'agit bien de la redéfinition de f de A void g(); // il ne s'agit pas de la redéfinition de g de A car // fonction non constante virtual void h(char); // il s'agit bien de la redéfinition de h de A void k(); // k non virtuelle dans A donc ce n'est pas une dérivation }; //****************** class C { virtual void f() final ; // ne peut pas être redéfinie dans une classe dérivée // prend du sens si C dérive d'une classe ayant déjà f virtual virtual void g() const; virtual void h(char); void k(); }; class D : public C { void f(); // pas possible : erreur. De plus il veut que override soit précisé void g() override ; // pas possible n'est pas une redéfinition // fonction non constante virtual void h(char); // le compilateur veut que override soit précisé void k() override ; // pas possible car k n'est pas virtuelle };

Polytech Marseille , Prog. o. o. 242

Généralisation de la liste entre { }

•  Pour le meilleur

–  Mais ne permet pas tout comme

•  par exemple initialiser à 0 un tableau de 1000 éléments •  Mais des constructeurs le permettent dans la classe vector

–  Vector<int> v(1000,0);

#include <iostream> using namespace std ; int main() { float * ptr ; ptr = new float[10] {0,1,2,3,4,5,6,7,8,9} ; // impossible avant for (int i=0 ; i<=9; i=i+1) cout << ptr[i] << " " ; cout << endl ; return 0 ; } /* mdaniel$ ./testbase 0 1 2 3 4 5 6 7 8 9 avec ptr = new float[10] {0,1,2,3,4,5} ; 0 1 2 3 4 5 0 0 0 0 */

Page 122: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

122

Polytech Marseille , Prog. o. o. 243

Généralisation de la liste entre { }

•  et du moins bien (du point de vue de votre serviteur !) #include <iostream> using namespace std ; int main() { int i ; // constructeur par défaut i=5 ; int j=5 ; // constructeur par recopie int k(5) ; // constructeur un paramètre int l {5} ; // constructeur un paramètre int m = {5} ; // constructeur par recopie cout << "i,j,k,l,m= " << i << "," << j << "," << k << "," << l << "," << m << endl ; return 0 ; } /* mdaniel$ ./pastropcool i,j,k,l,m= 5,5,5,5,5 */

Polytech Marseille , Prog. o. o. 244

« Pratique »

•  Obtention automatique du type

•  Encore une facilité –  decltype(itr) itrbis ; itrbis a le même type que itr ;

#include <iostream> #include <vector> using namespace std ; int main() { // vector<int> v(10) {0,1,2,3,4,5,6,7,8,9} ; //cela, le compilateur n'aime pas du tout // vector<int> v(10)= {0,1,2,3,4,5,6,7,8,9} ; //pas plus que cela vector<int> v(10) ; v= {0,1,2,3,4,5,6,7,8,9} ; //cela, oui ! for (auto itr = v.begin(); itr < v.end(); itr++ ) cout << *itr << " " ; cout << endl ; // la même chose pour les puristes vector<int>::iterator itv ; for (itv = v.begin(); itv < v.end(); itv++ ) cout << *itv << " " ; cout << endl ; return 0 ; } /* mdaniel$ ./auto 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 */

Page 123: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

123

Polytech Marseille , Prog. o. o. 245

« En vrac »

•  Le for généralisé : à méditer …

•  Fonction « = delete » : –  void adjust_size(…)= delete ; –  adjust_size est inutilable ;

•  Pointeur nullptr ; pas = 0 d’avant •  Conversion implicite en un pointeur de n’importe quel type

–  Ce qui ne fonctionnait pas correctement avant •  pas de conversion implicite en entier

##include <iostream> using namespace std ; int main() { // A compiler avec l'option -std=c++11 sur Mac float a[10] {0,1,2,3,4,5,6,7,8,9} ; for (int i:a) cout << a[i] << " " ; cout << endl ; return 0 ; } /* mdaniel$ ./testbase 0 1 2 3 4 5 6 7 8 9 */

Polytech Marseille , Prog. o. o. 246

« En vrac »

•  Fonction « lambdas » –  On passe une fonction courte en paramètre –  L’implémentation est faite directement dans l’appel –  Lire la doc !

•  Tables de hachage –  Conteneurs associatifs –  La clé est codée et sert d’index de la table de hachage –  4 conteneurs associés au 4 conteneurs associatifs, set, multiset, map,

multimap : •  unordered_set, unordered_multiset

–  la clé est la donnée (clés uniques ou pas) •  unordered_map, unordered_multimap

–  des clés + données (clés uniques ou pas)

•  Voir la doc pour tout ce qui n’est pas présenté ici !

Page 124: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

124

Polytech Marseille , Prog. o. o. 247

Sémantique du déplacement

•  Beaucoup plus compliqué …

•  Idée : éviter de faire des copies parfois lourdes (constructeur par recopie, opération d’affectation) en “vampirisant” des objets qui n’ont plus longtemps à vivre –  On les vide de leur information en la déplaçant

•  « Vampirisation » des adresses

–  On les laisse mourir (contrairement aux vampires !) –  Les objets vampirisés sont des objets temporaires, des rvalues –  Revient à faire des références (adresses) sur des rvalues

•  Ils sont bien quelque part !

–  Un nouveau type : référence sur une rvaleur T && ma_rvalue ;

•  Les objets du C++, la bibliothèque standard implémente cette notion en C++ 2011 –  Gain de performance potentiel –  A prévoir sur ses objets

Polytech Marseille , Prog. o. o. 248

Sémantique du déplacement

•  Prévoir … et implémenter ces fonctions si désiré

–  Cela ne fonctionnera évidemment que si ces fonctions existent –  Attention pour les classes génériques !

•  Risques si les classes instanciées ne le prévoit pas ou le prévoit mal

•  move : « convertir une lvalue en rvalue » pour utiliser la sémantique du déplacement. Retourne une référence sur une rvalue

Class A { A() ; A(const A &) // constructeur par recopie classique A(A &&) ; // constructeur par déplacement en « vampirisant » une rvalue … A & operator=(const A &); // affectation classique A & operator=(A &&) ; // affectation par déplacement en « vampirisant » une rvalue ... } ;

void swap(T & a, T & b) { T tmp = move(a); // constructeur par déplacement après « conversion » de a en rvalue a = move (b); // affectation par déplacement après « conversion » de b en rvalue b = move (tmp); // affectation par déplacement en « vampirisant » une rvalue } // seuls des échanges d’adresses ont été faits !

Page 125: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

125

Polytech Marseille , Prog. o. o. 249

Sémantique du déplacement

#include <iostream> using namespace std ; class T { public: int* ptr; T() { ptr= new int[100] ; } ~T() { delete[] ptr; } // constructeur par recopie T(const T & t) { ptr= new int[100] ; for (int i=0; i<100; i=i+1) ptr[i]=t.ptr[i] ; } // affectation classique T & operator=(const T & t) { // ici c'est simple, les zones mémoire ont la même taille for (int i=0; i<100; i=i+1) ptr[i]=t.ptr[i] ; return *this ; } // constructeur par déplacement T(T&& t) { // grâce à &&, on a récupéré une adresse ptr=t.ptr ; // on vampirise les données de t t.ptr = nullptr; // il ne faut pas que t continue d'être associée à la zone // mémoire car elle disparaitrait quand t va disparaitre cout << "contructeur par deplacement" << endl ; }

La suite -à

La suite : / affectation par déplacement T & operator=(T && t) { // grâce à &&, on a récupéré une adresse delete[] ptr ; // il ne faut pas laisser fuiter la mémoire ptr=t.ptr ; // on vampirise les données de t t.ptr = nullptr; cout << "affectation par déplacement " << endl ; return * this ; } /* autre solution plus élégante T & operator=(T && t) { // utilisation de la fonction swap générique swap(ptr,t.ptr) ; // la mémoire qu'avait this avant return * this ; // l'affectation sera détruite quand t } // va disparaitre */ } ;

Polytech Marseille , Prog. o. o. 250

Sémantique du déplacement

// test de la classe précédente void swap(T & a, T & b) // cette fonction swap est définie pour le type T { // donc pas d’utilisation de la fonction générique T tmp = move(a); // constructeur par déplacement après « conversion » de a en rvalue a = move (b); // affectation par déplacement après « conversion » de b en rvalue b = move (tmp); // affectation par déplacement en « vampirisant » une rvalue } int main() { T v1,v2; for (int i=0; i<100; i=i+1) { v1.ptr[i] = i ; v2.ptr[i] =-i ; } swap(v1,v2) ; cout << "v1=" ; for (int i=0; i<10; i=i+1) cout << v1.ptr[i] << " " ; cout << endl ; cout << "v2=" ; for (int i=0; i<10; i=i+1) cout << v2.ptr[i] << " " ; cout << endl ; } /* mdaniel$ ./vampire contructeur par deplacement affectation par déplacement affectation par déplacement v1=0 -1 -2 -3 -4 -5 -6 -7 -8 -9 v2=0 1 2 3 4 5 6 7 8 9 */

Ce n’est qu’un exemple d’utilisation

Page 126: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

126

Polytech Marseille , Prog. o. o. 251

Conclusions sur C++

Polytech Marseille , Prog. o. o. 252

Conclusions sur C++

•  Langage –  difficile –  performant

•  programmation orientée objets •  ouverture vers le C

–  complexe à lire –  ayant des restes C (défaut !) –  nécessitant des règles d’utilisation et de présentation –  une pratique régulière

–  en quelque sorte une référence (& !) –  permettant une migration vers l’apprentissage d’autres langages

Page 127: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

127

Polytech Marseille , Prog. o. o. 253

Conclusions sur C++

•  Ce cours est une introduction au langage C++

•  « La bible » comprend 911 pages serrées

•  L’apprentissage du langage –  ne peut être que progressif –  n’a d’intérêt que face à des problèmes précis –  lire la documentation sera un passage obligé

•  en particulier pour la bibliothèque standard –  complexe et complète

•  les exceptions

Polytech Marseille , Prog. o. o. 254

Conclusions sur C++

Il faut prendre du recul –  se situer le plus possible au niveau conceptuel

•  les concepts restent, les langages changent

–  refuser les astuces et avoir une logique « multi-langages »

Page 128: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

128

Polytech Marseille , Prog. o. o. 255

Glossaire partiel (1/3)

•  Abstraction de données •  Principe selon lequel un objet est complètement défini par son interface,

c’est-à-dire l’ensemble des opérations qui lui sont applicables. La réalisation de ces opérations et la représentation « réelle » de l’objet restent cachées et inaccessibles du monde extérieur.

•  Classe •  description d’une famille d’objets ayant même structure et même

comportement. Elle regroupe un ensemble de données et de traitement (méthodes ou fonctions membres).

•  Une composante statique (la structure de données) •  Une composante dynamique (les méthodes) •  c’est un moule pour créer des objets, une entité conceptuelle

•  Encapsulation •  Mécanisme permettant de regrouper dans une même entité des données et les

opérations qui s’appliquent à celles-ci. Permet l’abstraction de données.

Polytech Marseille , Prog. o. o. 256

Glossaire partiel (2/3)

•  Généricité •  Mécanisme qui permet de définir un modèle de programme dans lequel des

types ou des opérations ne sont pas fixés a priori. Les modules génériques permettent de créer des réalisations (instanciations) de ces données ou opérations où l’on précise les types et les opérations.

•  Héritage •  Mécanisme permettant le partage et la réutilisation de propriétés entre les

objets. C’est une relation de généralisation/spécialisation qui organise les objets en une structure hiérarchique

•  Instance/Instanciation •  Représentant « physique » d’une classe qui est obtenu par moulage du

dictionnaire des variables de la classe et dont le comportement est défini par les méthodes de la classe.

•  Objet particulier créé en respectant les règles de la classe

Page 129: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

129

Polytech Marseille , Prog. o. o. 257

Glossaire partiel (3/3)

•  Polymorphisme •  étymologiquement : plusieurs formes. En langage objet, on appelle

polymorphisme (ou mieux polymorphisme d’héritage), la capacité pour une même variable de désigner successivement des objets de types différents.

Polytech Marseille , Prog. o. o. 258

Bibliographie succincte

•  Le langage C++, B. Stroustrup, Addison-Wesley, différentes éditions (la norme C++ de 98 est dans la version 3)

•  Langage C++, la proposition de standard ANSI/ISO expliquée, J. Charbonnel, Masson, 1996

•  Les langages à objets, langages de classes, langages de frames, langages d’acteurs, G. Masini, A. Napoli, D. Colnet, D. Léonard, K. Tombre, InterEditions, 1989

•  Le langage et la bibliothèque C++, Henry Garreta, Faculté des Sciences de Luminy, octobre 1999

•  Programmer en langage C++, C. Delannoy, Eyrolles, 8e édition, 3e tirage, 2016. •  Exercices en langage C++, C. Delannoy, Eyrolles, 2e tirage, 1998. •  Programmer efficacement en C++, Scott Meyers, Dunod, 2016. •  Conception et programmation par objets, pour du logiciel de qualité, B. Meyer,

InterEditions, 1990 •  Conception et programmation orientée objet, pour du logiciel de qualité, B.

Meyer, Eyrolles, 3e tirage, 2008 •  La programmation orientée objet, Hugues Bersini, 4e édition, Eyrolles, 2008

Page 130: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

130

Polytech Marseille , Prog. o. o. 259

Annexe 1

•  Utilisation d’un makefile (approche simplifiée) # fichier permettant la cohérence automatique des versions d'un # groupe de programmes # # la consitution de makefiles permet un traitement "haut de gamme" # de la mise à jour. L'utilisation se doit d'être étudiée en détail # # l'exécution d'un makefile s'obtient en tapant make # ce qui implique un seul makefile par répertoire # # attention, il faut introduire des indispensables tabulations (!) # ----------------------------------------------------------------------------- # cohérence du programme exécutable : essai_Complexe : essai_Complexe.o Complexe.o # # si nécessaire : édition des liens

g++ -o essai_Complexe essai_Complexe.o Complexe.o -lm # ----------------------------------------------------------------------------- # cohérence de l'objet essai_Complexe.o : essai_Complexe.o : essai_Complexe.cxx Complexe.h # # si nécessaire : compilation

g++ -c essai_Complexe.cxx # ----------------------------------------------------------------------------- # cohérence de l'objet Complexe.o : Complexe.o : Complexe.cxx Complexe.h # # si nécessaire : compilation

g++ -c Complexe.cxx # # fin

Polytech Marseille , Prog. o. o. 260

•  Création de bibliothèques pour l’édition des liens (UNIX) –  bibliothèques statiques

•  les .o sont inclus pour former l’exécutable –  bibliothèques dynamiques

•  des liens vers les .o sont dans l’exécutable •  la bibliothèque n’est chargée qu’une fois en mémoire

•  bibliothèque statique : proposition d’une syntaxe particulière

–  voir aussi commande ranlib (création d’index dans l’archive)

Annexe 2

ar -cru libSClasses_C++.a (création d’une archive vide) ar -r libSClasses_C++.a complexe.o (contient complexe.o) ar -cru libSClasses_C++.a *.o (création d’une archive contenant *.o) ar -t libSClasses_C++.a (liste le contenu de l’archive) ar -d libSClasses_C++.a complexe.o (supprime complexe.o de l’archive)

Page 131: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

131

Polytech Marseille , Prog. o. o. 261

•  Utilisation g++ -o essai_Complexe essai_Complexe.o -lm -L./ -lSClasses_C++ ou

g++ -o essai_Complexe essai_Complexe.o -lm -L./ libSClasses_C++.a

(-L : chemin d’accès)

•  bibliothèque dynamique : proposition d’une syntaxe particulière

•  Utilisation g++ -o essai_Complexe essai_Complexe.o -lm -L./ -lDClasses_C++

•  Attention –  voir commande man –  mélange entre les types de bibliothèques : contraintes d’éditions de liens –  attention aux conflits de noms résolus par le système

Annexe 2

g++ -shared -o libDClasses_C++.so *.o (création d’une archive contenant *.o)

Polytech Marseille , Prog. o. o. 262

Problème des redéfinitions

// fichier bidon.h // autre fichier #include <iostream> #include <iostream> #include "entete1.h" #include "entete1.h" #include "entete2.h" #include "bidon.h"

… …

•  2 solutions

1) Réorganiser tous les fichier d’entête et les inclusions de tous les développeurs ...

2) Utiliser les directives de compilation

Annexe 3 (1/2)

Page 132: Introduction à la Programmation Orientée Objetmarc.daniel.perso.luminy.univ-amu.fr/poo/poo-cours-2dia.pdf · Programmation Orientée Objet Marc DANIEL ... • De C à C++ 19

132

Polytech Marseille , Prog. o. o. 263

Problème des redéfinitions

•  « La » solution (du langage C) : création d’un symbole –  qui sert de drapeau permettant de savoir si le fichier a déjà été inclus –  à faire systématiquement pour tout fichier .h

•  (avec des bons noms de symbole !) –  en association avec les directives du préprocesseur #...

// fichier bidon.h #ifndef BIDON_H Si le symbole BIDON_H n’existe pas alors #define BIDON_H créer le symbole BIDON_H // le corps du fichier .h définir effectivement le fichier .h

(donc l’inclure quand on l’utilise) sinon

... c’est que on a déjà rencontré une fois un #include "bidon.h", donc ne rien faire

#endif finsi

Annexe 3 (2/2)