64
Langage C++ - Jean-Marc Pierson - INSA Lyon Plan du cours Langage algorithmique Notion de qualité des algorithmes Le langage C++ Langage algorithmique (LA) Pourquoi faire ? s'accorder sur une manière de décrire un algorithme s'abstraire des contraintes pures de codage (oubli de point-virgule, …) se concentrer sur le fonds plutôt que sur la forme LA : comment faire ? être rigoureux dans ses descriptions lever toutes les ambiguïtés décrire un algorithme dans une forme telle que la passage au codage ne pose plus aucun problème, pour que cette opération de codage devienne une simple mécanique de traduction du LA vers le langage cible LA : comment faire (suite) Techniquement : – Indenter pour séparer les divers blocs – Bien repérer le début et la fin des instructions Ne pas hésiter à mettre des commentaires : en début de méthode ou de fonction expliquant son fonctionnement général, ou dans l'algorithme lorsque c'est nécessaire à la compréhension de l'algorithme (pas du style : i := i + 1 // commentaire : on incrémente la variable i !)

Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 1Département Informatique de l'INSA- Jean-Marc Pierson

Langage C++ - Jean-Marc Pierson -INSA Lyon

Plan du cours

• Langage algorithmique

• Notion de qualité des algorithmes

• Le langage C++

Langage algorithmique (LA)

Pourquoi faire ?

• s'accorder sur une manière de décrire un algorithme

• s'abstraire des contraintes pures de codage (oubli de point-virgule, …)

• se concentrer sur le fonds plutôt que sur la forme

LA : comment faire ?

• être rigoureux dans ses descriptions• lever toutes les ambiguïtés• décrire un algorithme dans une forme telle

que la passage au codage ne pose plus aucun problème, pour que cette opération de codage devienne une simple mécanique de traduction du LA vers le langage cible

LA : comment faire (suite)• Techniquement :

– Indenter pour séparer les divers blocs– Bien repérer le début et la fin des instructions

• Ne pas hésiter à mettre des commentaires : en début de méthode ou de fonction expliquant son fonctionnement général, ou dans l'algorithme lorsque c'est nécessaire à la compréhension de l'algorithme

(pas du style : i := i + 1 // commentaire : on incrémente la variable i !)

Page 2: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 2Département Informatique de l'INSA- Jean-Marc Pierson

LA : quelques exemples

si expression alorsinstruction1

sinoninstruction2instruction3

fin_si

tantque expression faireinstruction1instruction2

fin_tantque

nom_var := expression

entier nombreLu

caractère caractereLu

Déclaration

Affectation

Test

Tant quePourpour expression faire

instruction1instruction2

fin_pour

Exemple : factoriellefonction factorielle (entier n:0..+inf) renvoie entier

entier fdebut

f := 1 tant que (n <> 1) faire

f := f * n n := n – 1

fin_tantqueretourne f

fin

Évaluation de la complexité

• Complexité temporelle : temps d'exécution ;nombre d'instructions élémentaires à faire dans l'algorithme à évaluer (question : qu'est-ce qu'une instruction élémentaire ?);

• Complexité spatiale : place occupée par les données;

• dépendent de la représentation des données (type abstrait utilisé) et du nombre d'éléments stockés

Complexité temporelle• on note O(f(n)) la complexité d'un algorithme, où n est

le nombre d'éléments à traiter par l'algorithme; ceci signifie que la complexité peut-être estimée par c.f(n)où c est une constante;

• on s'intéresse à son comportement asymptotique lorsque n est grand

• quelques exemples : – O(1) : indépendant de n ; ex : récupération d’un élément d'un

tableau – O(n) : parcours d'un tableau de n éléments– O(n3) : multiplication de deux matrices n*n

Page 3: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 3Département Informatique de l'INSA- Jean-Marc Pierson

Produit de matriceb11 b12 b13 ………. b1n

b21 b22 ………...…b2n

..

....... bnn

a11 a12 a13....... a1n x11 x12 …..a21 a22 ….…… a2n ….… ….…… ann xnn

x11 = a11*b11 + a12*b21+… + bn1*a1n

n multiplications et n-1 additions = 2n-1 op.

n2*(2n-1)

O(n3)

Complexité et vitesse d’exécutionMesure de la vitesse : pour une vitesse d'exécution de 1

teraflops (=1000 gigaflops = 106 megaflops = 109

flops = 1 milliard d’opérations en « virgule flottante » par seconde), une complexité en O(n3), avec n=100000=105 donne 1015 instructions élémentaires et donc 106 secondes, soit plus de 11 jours et demi !

• le plus puissant aujourd’hui : 35 Teraflopshttp://www.top500.org/

Complexité spatiale

• On peut aussi la présenter sous la forme O(f(n))

• mais on préfère la présenter sous la forme de nombre d'octets (à cause de la constante c qui rend trop imprécise l'estimation : pour n=100000 éléments, O(n) peut aussi bien exprimer 400000 que 1200000 octets !)

"Programmation objet en C++"• introduction à la P . O . O, le C++ et le C• préprocesseur• types des données manipulables • classes/méthodes/fonctions• portée des noms/durée de vie des objets • fonctions ordinaires/bibliothèques• instructions• expressions/opérateurs• surcharge d'opérateurs • classes et fonctions génériques• héritage• compléments : exceptions/conversions/"friend"• La librairie standard C++ / Les entrées sorties

Page 4: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 4Département Informatique de l'INSA- Jean-Marc Pierson

Plan "Programmation objet en C++"

• introduction à la P . O . O, le C++ et le C• préprocesseur• types des données manipulables • classes/méthodes/fonctions• portée des noms/durée de vie des objets • fonctions ordinaires/bibliothèques• instructions• expressions/opérateurs• surcharge d'opérateurs • classes et fonctions génériques • héritage• compléments : exceptions/conversions/"friend"• La librairie standard C++

La programmation orientée objet • Un programme exécutable = ensemble d'OBJETS

communiquant par envoi de messages . • Tout objet est une instance d'une CLASSE, dans laquelle

sont définis– les informations encapsulées (attributs)– les algorithmes des traitements de messages(méthodes) .

• Programme source = ensemble de définitions de classes (et de fonctions)

• Une classe peut être une spécialisation d'une autre classe : "héritage"

Intérêts de l'approche objet

• Tous ceux de l'approche "types abstraits"- Modularité- Séparation spécification/réalisation- Encapsulation

• + Réutilisabilité- Spécialisation via l'héritage- Constitution de bibliothèques de classes

• + Évolutivité- grâce à l'héritage

Terminologie LOO• classe concrète : une classe dont toutes les méthodes

sont réalisées• classe abstraite : une classe dont au moins une

méthode n'est pas réalisée• classe générique : une classe "paramétrable" : par

exemple, une Pile peut être générique et être utilisée soit comme une pile d'entier, soit comme une pile de réels

Page 5: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 5Département Informatique de l'INSA- Jean-Marc Pierson

Terminologie LOO (suite)

• Sous-classe (dérivée, descendant, spécialisation)

relation "Est-Un" ("sorte de") par exemple :

un Salarié est une sorte de Personneun Cercle est une sorte de FormeGeometrique

• Super-classe (ancêtre)

Terminologie LOO (fin)

• Objet = "Instance d'une classe"par exemple, Paul est une Personne (Paul est une instance de la classe Personne)

• Attribut = variable d'instancepar exemple, un attribut de Paul est son Nom; un autre attribut pourrait être son Adresse

• Méthode d'instance = réaction d'un objet à la réception d'un message

• variable de classe, méthode de classe : non reliées à une instance, propre à la classe

Principales caractéristiques du C++• Langage puissant• Construit sur le langage C:

– un meilleur C– programmation par types abstraits– programmation objet

• Réutilisation des bibliothèques C• Manipulation mixte d'objets et de variables de types

primitifs C• Moins pur que d'autres LOO (Smalltalk, Java)• Nombreux environnements de développement

Principales caractéristiques du C++ (suite)

• Surcharge de fonctions• Surcharge d'opérateurs• Généricité des classes et fonctions• Librairies standards de classes et fonctions • Héritage multiple

Page 6: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 6Département Informatique de l'INSA- Jean-Marc Pierson

C++ et les autres langages

Simula 67

Ada 95

Ada

C

Smalltalk

70

80

90

96

Pascal

C++Eiffel

Java

Langages objet

Références Web• Site Web :

– http://www.cplusplus.com– http://casteyde.christian.free.fr/cpp/– http://www.icce.rug.nl/docs/cplusplus/cplusplus.html– http://www.BruceEckel.com– http://www.examware.com/tutor6.html– http://devcentral.iftech.com/learning/tutorials/c-

cpp/cpp/– http://perso.club-internet.fr/pprados/Langage/CPP/

Bibliographie• Bjarne Stroustrup. "Le langage C++". 2ème édition. Addison-

Wesley, 1992• Margaret Ellis & Bjarne Stroustrup. "The Annotated C++ Reference

Manual". Addison-Wesley, 1990. • Scott Meyers. "Effective C++, 50 Specific Ways to Improve Your

Programs and Designs". Addison-Wesley, 1992. • Scott Meyers. "More Effective C++, 35 New Ways to Improve Your

Programs and Designs". Addison-Wesley, 1996.• J. O. Coplien. "Programmation avancée en C++". Addison-Wesley,

1992.

Le langage C

• langage évolué, typé, structuré• "programmation système"

– Unix– Concision-Efficacité

• Nombreuses bibliothèques• Bonne portabilité• Compilation séparée

Page 7: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 7Département Informatique de l'INSA- Jean-Marc Pierson

Structure d'un programme C++ • PROGRAMME exécutable =

ensemble de "modules objet "(binaire)• Module objet = traduction d'un "texte source"• Texte source = ensemble

– de définitions de classes, fonctions, données– de directives pour le préprocesseur

• Point d'entrée = fonction main( )

Les concepts du langage C++

type utilisateur

classe

donnée : variable ouconstante

expression

instruction

opérateur

type prédéfini

formealgorithmique

exception

héritage

généricité

méthode oufonction

Les concepts du langage C++

type utilisateur

classe

donnée : variable ouconstante

expression

instruction

opérateur

type prédéfini

formealgorithmique

exception

héritage

généricité

méthode oufonction

float CL::f(int a) {float b;b := 1/a; return b;

}

b := 1/a

1/a

/1 et aint, float

div par 0classe CL

Méthode/Fonction • En C++, il existe 2 sortes de fonctions, ayant

un grand nombre de points communs(paramétrage, exécution, surcharge, notation fonctionnelle/opérateur, …)

– les méthodes définies dans une classe et applicables aux objets, instances de cette classe:

objet . Méthode(….)– les fonctions "ordinaires" définies en dehors de

toute classe : fonction(…)les fonctions C sont, bien sûr, dans cette famille, par exemple la fonction "main")

Page 8: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 8Département Informatique de l'INSA- Jean-Marc Pierson

Méthode/Fonction

• Définition dans UN SEUL module source• Appel dans une instruction dans une

méthode/fonction située dans un module source quelconque

• Déclaration dans chaque module où ondésire l'utiliser

( le plus souvent dans un fichier d'interface -de classe ou de module - inclus par #include)

CONTEXTES d'OCCURRENCE d'une méthode/fonction

Exemple: programme C++ simple/* texte source ( compt .C ou compt.cpp) d'un programmecomptant le nombre de lignes du fichier texte lu sur l'entrée standard (utilisation des classes d'E/S standard) */#include <iostream> // lecture des interfaces des classes d'entrées-sortiesint main () // programme principal{ char carac ; int nombreLignes = 0 ;

while (cin . get(carac) ) // tant que l'on n'a pas lu tout le texte // à partir du flot d'entrée standard "cin"

{ if (carac == '\n' ) // si c'est une fin de ligne, on{ ++ nombreLignes ; // incrémente le nombre de lignes}}

cout << nombreLignes <<" lignes\n" ;

// affichage du résultat sur le flot de sortie standard "cout"}

Exécution du programme

% g++ compt.C -o compt Compilation-Reliure du programme compt.C

% compt Exécution avec lecture claviervoila une première ligneet une deuxième

et la dernière ligne (suivie d'un CTRL d)

3 lignes% compt < compt.C Exécution avec lecture fichier disque

15 lignes

Chaîne de production

cc (gcc, g++, …) enchaînent les opérations en fonction : -des options de la commande:

-E : étape 1 -S : étapes 1-2-c : étapes 1-2-3 défaut : étapes 1-2-3-4-0 : optimisation dans l'étape 2

-et des suffixes des fichiers à traiter:. c . C (.cpp) . o

préprocesseurcpp

compilateurc/c++

relieurld

assembleuras

texte sourcemodule

objet programme

1 2 3 4

texte sourceassembleur

Page 9: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 9Département Informatique de l'INSA- Jean-Marc Pierson

"Programmation objet en C++"Plan

• introduction à la P . O . O, le C++ et le C

• préprocesseur• types des données manipulables • classes/méthodes/fonctions• portée des noms/durée de vie des objets • fonctions ordinaires/bibliothèques• instructions• expressions/opérateurs• surcharge d'opérateurs • classes et fonctions génériques • héritage• compléments : exceptions/conversions/"friend"• La librairie standard C++

Le préprocesseur : cpp

• Inclusion de fichier source• Substitution d'identificateurs• Traduction conditionnelle

DIRECTIVES #

Inclusion de fichier source• Rôle : permet d'importer, depuis un fichier

source, dans tout module qui en a besoin, des– définitions de types (classes, . . . ), constantes– déclarations de fonctions

• Syntaxe :#include "cheminAccesFichierAInclure"

(par exemple dans le répertoire de travail)

#include <NomDeFichierPublic>recherche du fichier à inclure dans le(s) répertoire(s) standardexemple UNIX : /usr/include /usr/include/sys . . .

Substitution d'identificateurs(peu utile en C++, à éviter)

• Rôle :– définition d'identificateurs pour traduction conditionnelle– macro-instructions

• Syntaxe :#define identificateur chaineDeCaractères

exemples : #define boucle for( ; ;)#define _MODULEH

#define macro(param1,param2) chaineexemple : #define Afficher(a,b) std :: cout << (a) << (b)

Page 10: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 10Département Informatique de l'INSA- Jean-Marc Pierson

Traduction Conditionnelle• Rôle:

– Aides à la mise au point– Eviter les inclusions multiples de fichier– Gestion de versions

• Syntaxe :#ifdef identificateur

phrases C++ ou directives cpp#endif

• exemples : macro assert (condition) ;#ifdef DEBUGcout << "Mise au point : x =" << x << endl;#endif

"Programmation objet en C++"Plan

• introduction à la P . O . O, le C++ et le C• préprocesseur

• types des données manipulables• classes/méthodes/fonctions• portée des noms/durée de vie des objets • fonctions ordinaires/bibliothèques• instructions• expressions/opérateurs• surcharge d'opérateurs • classes et fonctions génériques • héritage• compléments : exceptions/conversions/"friend"• La librairie standard C++

les Types des données C++

• Donnée : toute valeur manipulée dans un programme C++, variable ou constante

• Déclaration : association d'un nom et d'un type• Type : caractérise

• la représentation physique (place mémoire)sizeof (type) sizeof variable

• l'ensemble des valeurs possibles• l'ensemble des opérations possibles• la possibilité ou non de modification (préfixe const)

• Définition : déclaration + réservation mémoire

Déclaration• Syntaxe :[const] nomDuType nomDeLaVariable [= valeurInitiale] ;

• Exemples :int nombre ; // type primitifbool trouve = false ; // type primitifconst unsigned int NBCAR = 130 ; // idemstring nomFichier ; // classe standardchar ligne [NBCAR] ; // tableau de type primitifNoeud * racineArbre ; // pointeur sur une classe

Page 11: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 11Département Informatique de l'INSA- Jean-Marc Pierson

Les différents types

• Types primitifs : entiers, énumérations, réels, booléens --> pas de fichiers (classes définies dans la librairie)

• Types dérivés : tableaux, pointeurs, références--> de type quelconque (primitif, dérivé, classe)

• Types définis par l'utilisateur : classes--> définition d'un ensemble d'opérations (méthodes) manipulant

des données, de type quelconque (primitif, dérivé, classe)

--> la solution en C++ pour couvrir tous les besoins spécifiques

• Nom d'alias pour les types : typedef

Types primitifs

• ENTIERS :– de différentes tailles : char, short, int, long– signés ou non : signed (par défaut), unsigned

• BOOLEEN :– bool pouvant prendre les valeurs true, false

• REELS : (virgule flottante)– de différentes précisions : float, double, long double

Les types primitifs (indicatif)char ou signed char 8 bits -128 127unsigned char 8 bits 0 255int (sur proc 32bits) 32 bits –2147483648 2147483647unsigned int 32 bits 0 4294967295short intshort 16 bits -32768 32767unsigned short intunsigned short 16 bits 0 65535long intlong 32 bits –2147483648 2147483647unsigned long intunsigned long 32 bits 0 4294967295float 32 bits 1.175 E – 38 3.402 E + 38double 64 bits 2.225 E – 308 1.797 E + 308

Enumération• Permet de définir un nouveau type (sorte d'entier) ne

pouvant prendre que des valeurs désignées par des noms ex : enum Couleur { ROUGE, VERT, ORANGE} ;//une variable de type Couleur ne peut prendre qu'une des valeurs constantes :// ROUGE (0) VERT (1) ORANGE (2)// définition d'une variable de type COULEUR

Couleur feux = ROUGE ;

feux = 1 ; //affectation erronée

• On peut forcer les valeurs (autres que 0,1,2, . . . , de type char, short, int . . . ):

enum Taille { GRAND=100, MOYEN =10, PETIT=1} ;

• On peut simplement regrouper des noms de constantes:enum {OK, SATURATION, DOUBLE_DEFINITION} ;

Page 12: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 12Département Informatique de l'INSA- Jean-Marc Pierson

Types dérivés• TABLEAU : collection ordonnée de N (constante) éléments

de même type (quelconque : primitif, dérivé, classe), accessibles par leur rang (0 . . N-1) : [ ]

• POINTEUR : donnée contenant l'adresse d'une donnée d'un certain type : *

• REFERENCE : nom alternatif pour un objet (surtout utilisé pour le passage d'arguments à une fonction et le retour du résultat d'une fonction) : &

Tableau• Initialisation possible par une suite de valeurs• Accès à un élément par l'opérateur d'indexation [ ]• Possibilité de tableau de tableau de . . . • Le nom d'un tableau T désigne l'adresse de son premier

élément : – T est équivalent à l'adresse du 1er élément notée &T[0]

• La classe standard « vector » est une généralisation du type tableau, donc à utiliser préférentiellement

• En C, les chaînes de caractères sont représentées par des tableaux de char . En C++, on préfère utiliser la classe standard « string »

Pointeurs• Usages :

– accès à des objets créés à la demande, donc implantés dynamiquement en mémoire centrale

– parcours séquentiel d'un tableau – modification depuis une fonction des variables de la fonction appelante

(alternative : passage par référence)

• Accès à – l' objet pointé par *– un membre (méthode ou attribut) de l'objet pointé par ->– un élément i d'un tableau pointé par [i]

• Attention à la signification de l'affectation !

Lien pointeur/mémoire

int i;

i = 3;

int *pi;

pi = & i;

@ MémoireContenu de la

mémoire

// ici, on a pi=&i=0xff00 et *pi=i=3

3

0xff00

0xff00

0xff03&pi

Ici, on dit que l ’on déréférence pi

Page 13: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 13Département Informatique de l'INSA- Jean-Marc Pierson

Lien pointeur/mémoire (suite)int T[]={3,10,100,22};

int *pT, *pi;

pT = T;

pi = &T[2];

Adresses mémoire

Contenus de la mémoire

Zone mémoire réservée pour le

tableau T

30xff0010100

22

// pT = T = &T[0] = 0xff00 et *pT= T[0] = 3

// pi = &T[2] = 0xff02 et *pi = T[2] = 100

0xff05

0xff06&pT&pi

0xff00

0xff02

Exemples de types dérivésconst int LGMAX = 250 ; char ligne [LGMAX] ; const int LIGNES = 12 ; const int COLONNES = 6 ;double matrice [LIGNES] [COLONNES] ;const long PUISS10 [ ] = { 1 , 10 , 100 , 1000 } ;

char * ptr = ligne ; // ptr contient l'adresse d'un char (&ligne[0])

char * liste [ N] ; // liste est un tableau contenant N pointeurs de char

// jour est un tableau de 7 string constantesconst string jour [ ] = { "lundi", "mardi",

"mercredi","jeudi", "vendredi","samedi", "dimanche"} ;

Les références• N’existent pas en C• Permettent de créer des synonymes

d’identificateurs• Sont toujours initialisées à leur déclaration• exemple :int i; // i est un entier

int &ri=i; // i est une référence sur l’entier i

ri = ri+1; // équivalent à i=i+1

• i et ri font références à la même variable

Lien pointeurs/références• Déjà vu sur la manipulation de pointeurs :int i=0;int *pi=&i;*pi=*pi+1; // Manipulation de i via pi.

• Si on fait passer l'opérateur & de la deuxième ligne à gauche del'opérateur d'affectation :

int i=0;int &* pi = i; // Cela génère une erreur de syntaxe mais nous l'ignorons pour les besoins de l'explication.

*pi=*pi+1;

• En utilisant des références :int i=0;int &ri=i;ri=ri+1; // Manipulation de i via ri.

Page 14: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 14Département Informatique de l'INSA- Jean-Marc Pierson

Allocation dynamique de mémoire : opérateurs new/delete

Exemple :T * p1= new T ; // T est un type primitif ou une classe

// p1 pointe sur l'élément de type T qui a été créé

int nombreElements ;. . . . . . . . // calcul de nombreElements

T * vecteur = new T [nombreElements ] ;// création d'un tableau de "nombreElements" T// vecteur pointe le premier élément si création OK// vecteur[i] désigne le ième élément// si la création est impossible, exception bad_alloc

delete p1 ; // libération d'un élément isolé

delete [] vecteur ; // libération d'un tableau d'objets

Définition d'alias pour un type existant : typedef

• Syntaxe :typedef nomTypeExistant NouveauNom ;

• exemples :

typedef unsigned int nombrePositif;

typedef std::map<string,string> lexique ;

typedef Noeud * ARBRE ;

• Utilisation nombrePositif n = 3;

"Programmation objet en C++"Plan

• introduction à la P . O . O, le C++ et le C• préprocesseur• types des données manipulables • classes/méthodes/fonctions

• portée des noms/durée de vie des objets• fonctions ordinaires/bibliothèques• instructions• expressions/opérateurs• surcharge d'opérateurs • classes et fonctions génériques • héritage• compléments : exceptions/conversions/"friend"• La librairie standard C++

Portée des noms

PROGRAMME : global

"namespace"

classe

fonctionbloc

Page 15: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 15Département Informatique de l'INSA- Jean-Marc Pierson

Portée des noms• Pour un nom déclaré dans une fonction

portée limitée au bloc de sa déclaration ( à privilégier)

• Un nom déclaré dans une classe M (attribut, méthode, constante,type) appartient à l’espace de noms de la classe . – Il est visible depuis le corps des méthodes de la classe . – A l ’extérieur l’opérateur de portée M:: est nécessaire (sauf si le contexte

permet d'identifier M, par ex : instanceDeM . nomMethode(… . ) )

• Un nom déclaré dans un module (« namespace ») N appartient à cet espace de noms . – Il est visible par toutes les classes de ce namespace . – A l ’extérieur l ’opérateur de portée N :: est nécessaire

• Les autres noms sont globaux (à éviter)

Portée des noms (suite)• Les variables peuvent être déclarées n'importe où dans un

bloc.…{

int x;…{

int y;…}…

}...

porté de y porté de x

Une seconde variable x dans le second bloc ne peut pas être déclarée.

• Créer un namespace en C++ a pour but de définir un ensemble de variables, de classes et de fonctions partageant un même espace de nommage.

• Dans un espace de nommage, deux variables globales ou deux fonctions globales ou deux classes ne peuvent pas avoir le même nom.

• Un espace de nommage peut être défini par morceaux.• Une variable, une fonction ou une classe définie dans un

espace de nommage peut être utilisée dans un autre espace en spécifiant l’espace d’appartenance (avec l'opérateur ::)

Namespace Espace de noms

namespace std{ // définitions de classes, de fonctions, d'objets standard…

// par exemple :ostream cout ; // flot de sortie standard

...}

// utilisation de l'identificateur "cout" du "namespace" std :std::cout << "OK" ;

// ou // ouusing namespace std ; using std::cout ;cout << "OK" ; cout << "OK" ;

Page 16: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 16Département Informatique de l'INSA- Jean-Marc Pierson

Espace de nom, opérateur ::

namespace A {void f();

}

namespace Bvoid f();

}

#include "A.h"#include "B.h"

void main() {A::f();B::f();

}

A.h

B.h

main.C

Espace de nom (suite...)

namespace A {void f();

}

namespace Bvoid f();

}

#include "A.h"#include "B.h"

using namespace A;

void main() {f(); // ok, f() n ’est connu

// que dans l ’espace // de nom A

B::f();}

A.h

B.h

main.C

Espace de nom (suite et fin)

namespace A {void f();

}

namespace Bvoid f();

}

#include "A.h"#include "B.h"

using namespace A;using namespace B;

void main() {f(); // non, ambiguïté !

}

A.h

B.h

main.C

?

?

Implantation mémoire des variables• Locales à un bloc d'une méthode/fonction : 3 modes d'allocation

– par défaut (auto)- implantation en mémoire dynamiquement (à l'exécution)

dans la zone "pile d'exécution"- initialisation possible par une expression variable

(ou une "suite d'expressions variables" si tableau)– en registre (register)

- implantation dynamique dans un des registres de l'UC– implantation statique en mémoire (static) à la compilation

• Globales (au programme)– implantation en mémoire statiquement– initialisation possible

Page 17: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 17Département Informatique de l'INSA- Jean-Marc Pierson

Durée de vie des objets

La durée de vie dépend du type de l’objet :• local à un bloc : créé à sa définition, détruit à la sortie

du bloc . • statique : créé au début de l'exécution du programme,

détruit à sa fin . • dynamique : créé et détruit sous contrôle du programme

(new/delete)• attribut d'un autre objet : créé (détruit) lors de la

construction (destruction) de l'objet contenant .

"Programmation objet en C++"Plan

• introduction à la P . O . O, le C++ et le C• préprocesseur• types des données manipulables • classes/méthodes/fonctions• portée des noms/durée de vie des objets

• fonctions ordinaires/bibliothèques• instructions• expressions/opérateurs• surcharge d'opérateurs • classes et fonctions génériques • héritage• compléments : exceptions/conversions/"friend"• La librairie standard C++

Surcharge de fonctions ordinairesC++ permet de définir des fonctions homonymes, c'est-à-dire de même nom, mais avec des listes de paramètres différentes. L'opération"nomFonction (liste arguments)" est identifiée par :nomFonction + nombre arguments + type arguments

Le compilateur C++ "calcule" un identificateur correspondant à l'ensemble, pour la génération du code objetExemple de 3 fonctions C++ homonymes mais distinctes :int traduire(int,int,int); // version 1

void traduire(int,int); // version 2

void traduire(int,char *); // version 3

// mais

int traduire(int,int);// erreur, car ambiguité avec la version 2 : le type de retour n'est pas pris en compte

Appel de fonctions C par un programme C++

Le codage utilisé par C++ pour identifier les fonctions appelées impose une déclaration spéciale pour reconnaître les fonctions écrites dans d'autres langages .

extern "C" char * strcpy ( char*, const char *) ;

ouextern "C"

{ < déclaration fonction1 >< déclaration fonction2 >

. . . . . . } ; // ceci est fait en général, dans les fichiers . h

Page 18: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 18Département Informatique de l'INSA- Jean-Marc Pierson

Programmation Modulaire

Interface

Définition de classe

Définition de constantes

Déclarations de fonctions exportées

module1 . h

Réalisation#include "mod.h"Réalisation de classeDéfinitions des fonctions

exportées

module1 . C

#include "mod.h" Module 2 (ou programme principal)utilisantmodule1

module1

Programmation modulaire

• Le code source d'une classe est, en général, divisé en deux fichiers : – fichier d'entête, déclaration (header file, généralement .h) : contient

la déclaration et une partie de la définition d’une classe ; nécessaire pour l'utilisation du module

– fichier de définition/réalisation (généralement .C, ou .cxx, ou .cpp) :contient la définition des fonctions membres et d’une partie des données membres (pour les classes), sinon la définition des fonctions

• Il est recommandé (mais pas imposé) de ne mettre qu'une classe par fichier

Bibliothèques, création

• On peut regrouper plusieurs fichier objet dans une bibliothèque regroupant des fonctionnalités : collection de fichier objet (.o)

• Création de fichier .a (bibliothèque statique) ou de .so (bibliothèque partagée) sous unix(exemple : libm.a, pour la bibliothèque mathématique sous Unix, grâce à l'utilitaire ar) ou de .dll sous windows

Bibliothèques, utilisation• Utilisation dans le fichier source du

programme :

• Utilisation à la compilation:g++ -o main main.C -lm

#include <iostream>#include <cmath>void main() {

cout << "la racine carré de 9 vaut : " << sqrt(9);}

En fait, inutile ici car g++ l’inclut automatiquement

Page 19: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 19Département Informatique de l'INSA- Jean-Marc Pierson

Bibliothèques

flots C++

fonctionsmathématiques C

fonctionsstandard C

bibliothèquede composants C++

Fichiers d'interfacesou d'entêtes

fstream

vector list string map

iostream

algorithm

cstdio cstring

cstdlibfcntl . h unistd . h

ctime

cmath

Fichiers archives ( . a)collection de . o

Interface avec le système L'accès aux primitives du système d'exploitation se fait par des

appels de fonctions de la bibliothèque, qui assurent l'interfaceavec le noyau .

Pas de différence syntaxique entre une fonction d'une bibliothèque d'accompagnement et une primitive du noyau .

exemple :primitives : open() read() fork()fonctions C: strcpy() sqrt()méthodes : istream::get()

Paramètres du "main"Le point d'entrée d'un programme exécutable (en général, la

fonction "main") peut être paramétré par une liste d'arguments :chaînes de caractères communiquée par la primitive système de lancement de l'exécution (exec sous Unix)

Paramètres :- entier donnant le nombre de chaînes (>=1)- tableau de pointeurs sur les différentes chaînes

int main (int nbreArguments, char * liste[]){ // accès au ième (1,2,3 . . . ) argument par liste[i]

// accès au nom du programme par liste[0]// accès au dernier argument par liste[nbreArguments-1]// . . . . . . . .

}

ExempleSupposons que l'on demande l'exécution du programme

"main" (dont le main a la définition précédente) par la commande:

% main donnees 5 tablenbreArguments = 4liste[0] = "main"liste[1] = "donnees"liste[2] = "5"liste[3] = "table"

Page 20: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 20Département Informatique de l'INSA- Jean-Marc Pierson

Mécanisme inline

• Les méthodes (ou fonctions) inline sont les méthodes dont le corps (la définition) est directement écrit dans la déclaration de la classe (fichier header) ou précédé par le mot-clé inline et écrit dans le fichier de réalisation (.C)

• Si une méthode est inline alors le compilateur insérera le code propre de la méthode au lieu d’utiliser une instruction d’appel à la fonction.

Mécanisme inline

• Les fonctions/méthodes inline doivent être utilisées seulement pour des fonctions/méthodes dont le code est très court.

• Avantage : efficacité en temps d'exécution• Inconvénients :

– taille code objet généré par la compilation– non masquage de la réalisation (Rappel : les programmes

utilisateurs d'une classe ou d'une fonction doivent avoir la vue sur le fichier header, pour avoir leur déclaration)

Méthodes/Fonctions inline

// classe Aclass A {

private:int m_a; // variable privée de classeA

public:// fonctions d'accès à la variable privée m_aint getA() const { return m_a; }inline void setA(int p_a);

};

// fonction qui renvoie le maximum de deux entiersinline int max(int a,int b)

{ return a<b?b:a; }

classeA.hclasseA.C

Une fonction (pas une méthode, donc déclarée en dehors de toute classe) peut aussi être inline(cas de max() ici). A chaque appel de celle-ci, elle sera remplacée par son code.

Une fonction directement écrite dans la déclaration de la classe est inline. (cas de getA() ici). Certains compilateurs ne la considèrent pas inline si elle est trop longue (utiliser alors le mot-clé inline).

// implémentation de la classe classeAvoid classeA::setA(int p_a) {

m_a=p_a;}

L’utilisation du mot clé inlinepermet de cacher l’implémentation de la méthode tout en profitant des avantages des fonctions inline

"Programmation objet en C++"Plan

• introduction à la P . O . O, le C++ et le C• préprocesseur• types des données manipulables • classes/méthodes/fonctions• portée des noms/durée de vie des objets • fonctions ordinaires/bibliothèques

• instructions• expressions/opérateurs• surcharge d'opérateurs • classes et fonctions génériques • héritage• compléments : exceptions/conversions/"friend"• La librairie standard C++

Page 21: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 21Département Informatique de l'INSA- Jean-Marc Pierson

Instructions, vue générale• Définition : type nom [initialisation] ;

• Instruction simple : expression ;

• Bloc : { suite d'instructions }• Instructions conditionnelles : if switch

• Instructions itératives : while do forbreak continue

• Retour de fonction : return

• Lancement d'une exception : throwSaut : goto

Instruction if// première formeif (condition) // condition : expression_entière ou booléenne

// ou TYPE var = expression_entière ou booléen{ suite-instr}// deuxième formeif (condition){ suite-instr1}else{ suite-instr2}

Booléens en C• ... n'existent pas ! • en C, la gestion des conditions (vrai/faux) se

fait se la manière suivante :– une expression est fausse si son évaluation donne

0– sinon l'expression est vraie !

int a = 3;if (a = = 3) {

// vrai }

if (int a=3) { // vrai

}

Instruction switch

switch (expression_entière){ case valeur1 : suite instr1 ;

break ;case valeur2 : suite instr2 ;

break ;. . . . . . default : suite instr ;

}

break ; : en fin de "suite instr i" pour passer à l'instruction suivant le switch

Page 22: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 22Département Informatique de l'INSA- Jean-Marc Pierson

Les instructions itératives (1)Tant que

while (condition) {suite instructions;

}

Tant que la condition est vraie, exécuter les instructions du bloc

do {suite instructions;

}while (condition);

Exécuter les instructions du bloc tant que la condition est vraie

Les instructions du bloc sont exécutées au moins une fois. La condition est évaluée après cette première exécution.

Les instructions itératives (2)Répéter

Les instructions itératives (3)Pour

for (initialisation; condition; incrémentation){suite instructions;

}

Tant que la condition est vraie, exécuter les instructions du bloc

Exécution de l’instruction d’incrémentation de la ou des variables de boucle après la suite d'instructions

Initialisation de la ou des variables de boucle

Les instructions itératives(complément)

• en C++, la ou les variables de boucle peuvent être déclarée dans l’instruction for.

for(int i=1;i<=10;i++) {...}

• L’opérateur , peut être utilisé entre autres pour les parties initialisation et incrémentation dans le cas où elles nécessiteraient plusieurs instructions.

for (i=1,j=1; ...; ...) {...}

Page 23: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 23Département Informatique de l'INSA- Jean-Marc Pierson

Lien entre instructions itérativesfor (i=1;i<=10;i++) x=x+i;

i=1

i<=10 ?

x=x+i

i++

OUI

NON

i = 1;while (i<=10) {

x=x+i;i++;

}

i = 1;if (i<=10) {

do { x=x+i;i++;

}while (i<=10);

}

Instruction itératives : coupures de boucle

BREAK et CONTINUE– break stoppe une boucle (par exemple, une

boucle infinie : la condition d’arrêt est définie à l’intérieure de la boucle et si la condition se réalise alors l’instruction break sort de la boucle et passe à l'instruction suivant la boucle)

– continue passe automatiquement à l’itération suivante sans exécuter les instructions suivantes de la boucle

Coupures de boucle (exemple)int i=0, x=0; while (true) {i++;if (i>10) break;if (i=>5 && i<=8) continue;x = x + i;

}cout << "i=" << i << "x=" << x;

"Programmation objet en C++"Plan

• introduction à la P . O . O, le C++ et le C• préprocesseur• types des données manipulables • classes/méthodes/fonctions• portée des noms/durée de vie des objets • fonctions ordinaires/bibliothèques• instructions

• expressions/opérateurs• surcharge d'opérateurs • classes et fonctions génériques • héritage• compléments : exceptions/conversions/"friend"• La librairie standard C++

Page 24: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 24Département Informatique de l'INSA- Jean-Marc Pierson

Expressions/opérateurs

expression : Combinaison d'opérandes à l'aide d'opérateurs . opérande : constante ;

variable ; // de type primitif, dérivé ou classe

expression . opérateur : opérateur prédéfini ;

opérateur défini par l'utilisateur .

L'évaluation de la valeur de l'expression est éventuellement précédée par des conversions des valeurs de certains de ses opérandes.

Constantes littérales • Numériques :

entières base 10 : 56base 8 : 075base 16 : 0xba7f

réelles (double précision)3.14 5.32e-2

• Entier codé sur 8 bits (ou 16 bits pour code étendu :"Unicode"):

caractère imprimable : 'a' ' ;'spécial : '\n' '\0' '\033' '\0x7a'

Les opérateurs sur entiers

Numériques+ - * / %

Comparaison== != > >= < <=

Logiques! && ||

(not and or)

bit à bit& | ^ ~>> <<

Affectation=

+= -= *= /= <<= >>= , … .

entiers

Les opérateurs sur réels

réels

Numériques+ - * /

Comparaison== != > >= < <= Affectation

=+= -= *= /=

Page 25: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 25Département Informatique de l'INSA- Jean-Marc Pierson

Incrémentation/Décrémentation

Sur entiers, réels et pointeurs, l'affectationvariable = variable +1

peut se raccourcir envariable++ ou en ++variable

post-incrémentation pré-incrémentation(valeur expression= variable) (valeur expression = variable+1)

idem avec -- pour la (post/pré)-décrémentation . Signification de l'opération " pointeur + 1 "Noter la différence entre *ptr++ et *++ptr

Expression conditionnelle condition ? expr1 : expr2

désigne une expression dont la valeur est expr1 si condition est vraieexpr2 sinon

// exemple : transformation d'un entier en code ASCII

unsigned char c ;// c est supposé contenir une valeur comprise entre 0 et 15

unsigned char cHexa = c + ((c >9) ? 'a'-10 : '0') ;// cHexa contient le code ASCII de la représentation hexadécimale de c

Chaînes de caractères littérales

• Exemples :"bonjour""\tResultats\n\t---------\n""Ceci " "est" " une" " seule" " chaine"

• Représentation physique :tableau de caractères terminé par le caractère nul ('\0')

Attention : Ne pas confondre 'a' avec "a"

• "bonjour" est de type const char [ 8 ]

Opérateurs sur tableaux

tableaux

accès au premier élément* tab

L ’affectation n'existe pas

accès à un élément

tab[ i ]

Rappel : tab = &tab[0]

Page 26: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 26Département Informatique de l'INSA- Jean-Marc Pierson

Opérateurs sur pointeurs

pointeurs

Addition/soustractiond'un entier à un pointeur

ptr +/- i

Comparaison== != > >= < <= Affectation

=+= -=

accès à l'élément pointé*ptr

ptr[ i ]*(ptr+i)

accès à un membrede l'objet pointéptr -> membre

Ordre de priorité sur les opérateurs

• Les opérateurs respectent l’ordre de priorité du C

.[ ]*( )

++--!~

*/%

+-

<<>>

<><=>=

==!= & ^ && ||?: =

Du moins en moins prioritaire

Pointeur et tableau • Nom d'un tableau = pointeur sur son premier élément• Accès aux éléments par opérateurs: * []• exemples:

char c ; char * ptr; char ligne [LGMAX];ptr = &c ; // opérateur "adresse de"ptr = ligne ;c = *ptr ;c = * (ligne+2) ; // addition d'un entier à un pointeur++ptr[-1];

• Différences :sizeof ligne=LGMAXsizeof ptr = 4

sizeof (char *) = 4sizeof (char) = 1

Pointeur et tableau ( suite )

Exemples de déclarations équivalentes :

void Calcul (char * ligne) ;

void main (int nbArg, char * liste[]) ;

void Calcul (char ligne []) ;

void main (int nbArg, char * *liste) ;

Page 27: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 27Département Informatique de l'INSA- Jean-Marc Pierson

• Le mot-clé const peut être utilisé avec les pointeurs.• Deux syntaxes = deux significations bien différentes

– le contenu de la zone mémoire pointée ne peut pas être modifiée :const int * x; ou int const * x;

autorisé : x=&y; illégal : *x=1;– la valeur du pointeur ne peut pas être modifiée :

int * const x;

autorisé : *x=1; illégal : x=&y;– rien ne peut être modifiée :const int * const x; ou int const * const x;

illégal : x=&y; et *x=1;

Pointeurs et const

La deuxième forme est plus claire. const est placé à droite de ce qui ne peut pas être modifié.

"Programmation objet en C++"Plan

• introduction à la P . O . O, le C++ et le C• préprocesseur• types des données manipulables • classes/méthodes/fonctions• portée des noms/durée de vie des objets • fonctions ordinaires/bibliothèques• instructions• expressions/opérateurs• surcharge d'opérateurs • classes et fonctions génériques

• héritage• compléments : exceptions/conversions/"friend"• La librairie standard C++

Généralités sur l'héritageDe nombreuses classes peuvent être conçues comme des

spécialisations de classes plus générales (relation EstUn ou SorteDe) .

L'héritage permet d'éviter de redéfinir dans une classe dérivée le comportement des classes ancêtres, et donc, de ne se préoccuper que du comportement particulier à la classe .

On organise les classes selon une hiérarchie (arbre d'héritage ou graphe si héritage multiple) .

Généralités (suite)• principe de SUBSTITUTION

Sémantique de l'héritageSi on a A <== . . . <==B ( B hérite de A)

alors B doit pouvoir s'employer partout où A est employé : Attention : l'inverse n'étant pas vrai

• Sous Typage (relation de préordre sur les types)Les descendants d'une classe en sont des sous-types . Si on a A <== B <== C <== . . . , tout objet instance d'une classe héritant de A (donc de classe A, B, C, . . . ) est de "type A" . On peut donc lui appliquer toutes les opérations définies dans la classe A .

Page 28: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 28Département Informatique de l'INSA- Jean-Marc Pierson

Arbres d'héritage

Collection Forme

Ligne

Cercle Carré

RectangleSéquence

Pile DictionnaireFile

Non_séquentielleEllipse

Principe de substitution : toute opération applicable à une instance de Forme doit être applicable à une instance de Ligne, Ellipse, Cercle, . .

Ensemble

Héritage en C++

class classeDérivée : [mode] classeDeBase

{ // compléments d' interface pour "classeDérivée"} ;

mode = public cas le plus fréquentprivate pour héritage partielprotected

Exemples d'héritage// Définition de la classe pixel par dérivation de la classe point

class Pixel : public Point // un pixel est un point

// ou une sorte de point

{ public :enum Couleur {NOIR, ROUGE, BLANC} ;Pixel(Couleur laCouleur, int abs, int ord);

// la construction d’un Pixel s’appuie sur la construction d’un Point : pas de constructeur particulier

void Colorer ( Couleur laCouleur = NOIR) { coul = laCouleur ;}

protected : Couleur coul ;

} ;

Visibilité des éléments héritésLe mode d'héritage conditionne la visibilité, dans la classe

dérivée, des éléments ( attributs et méthodes) hérités de la superclasse .

• Héritage public : accès aux "public" et aux "protected"• Héritage private : tous les éléments deviennent "private", mais on

peut indiquer explicitement les éléments "public" que l'on souhaite laisser "public", donc accessibles aux clients de la classe dérivée .

Utilisation de l'héritage pour réutilisation de code et non de comportement .

• Héritage protected: les éléments "public" deviennent "protected", les autres sont inchangés

Page 29: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 29Département Informatique de l'INSA- Jean-Marc Pierson

• class B : public A {…};– un objet de type B (ou un pointeur sur…) pourra toujours être vu comme un

objet de type A (ou comme un pointeur sur…)– accès depuis B aux données public et protected de A.

• class B : private A {…};– un objet de type B (ou un pointeur sur…) pourra être vu comme un objet de

type A (ou comme un pointeur sur…) depuis B ou les amis de B (« seuls B et ses amis savent que B hérite de A »).

– les données et fonctions public et protected de A ne sont pas accessibles dans les sous classes de B.

• class B : protected A {…};– un objet de type B (ou un pointeur sur…) pourra être vu comme un objet de

type A depuis B, les amis de B et les sous-classes de B.

Héritage et visibilité Héritage et visibilite

B hérite de A Dans B Héritagepublic protected private

public Oui Oui Ouiprotected Oui Oui Oui

Membre de A

private Non Non Non

B hérite de A A l’extérieur Héritagepublic protected private

public Oui Non Nonprotected Non Non Non

Membre de A

private Non Non Non

Appels des constructeurs/destructeurs

Classe A

Classe B

Classe C

Pour un objet de classe C (qui hérite de B qui hérite de A)

Appel de A( )

puis de B( )

puis de C( )

A la destruction

Appel de ~C( )

puis de ~B( )

puis de ~A( )

A la création

Liaison entre constructeursSi le constructeur de la superclasse a des arguments, on doit préciser,

avant le corps des constructeurs des classes dérivées (dans l'interface si "inline", sinon dans la réalisation de la classe), quels arguments lui transmettre, avec une syntaxe similaire à l'initialisation des attributs .

exemple:class Pixel : public Point{ public:

Pixel ( Couleur couleur, int abs = 0, int ord = 0) : Point(abs,ord), coul(couleur) {}// . . . . | |// . . . . appel du constructeur initialisation de l’attribut de Pixel

};

Page 30: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 30Département Informatique de l'INSA- Jean-Marc Pierson

Exemples d'héritage (1/2)#include "Point.h"class Forme{ public :

void Deplacer (Point vecteur) ;void Dessiner () const ; //définition?

Forme (Point orig) : origine(orig) {}~Forme() ;

protected : Point origine ;

} ;

Exemples d'héritage (2/2)class Rectangle : public Forme

// un Rectangle est une Forme{ public :

void Dessiner() const ; // redéfinitionRectangle ( Point basGauche, long longueur, long hauteur) : Forme (basGauche), diagonale (longueur, hauteur) {}~Rectangle() ;

protected : Point diagonale ; // attribut supplémentaire

};

class Carre : public Rectangle // un carré est un Rectangle{ public : Carre ( Point orig, long cote)

: Rectangle(orig , cote , cote) {}} ; // pas d'attribut ni d ’autre méthode spécifiques à Carre

Affectation d'objets/* supposons que la classe Point soit munie d'un constructeur

Point (int abs, int ord) ;et que la classe Pixel qui hérite de Point ait un constructeur

Pixel (Couleur laCouleur, int abs, int ord) ; */

Point p (1,2) ;

Pixel px (Pixel::NOIR, 3, 5);p = px ; // autorisé, affectation partielle

// p demeure un Point ; p est en (3,5)

px = p ; // interdit

//Noter que le type Couleur étant défini dans l'espace de noms de Pixel,// on doit préciser cette appartenance dans l'écriture des valeurs du type Couleur, comme ici "Pixel :: NOIR"

Affectation de pointeurs d'objets

Point p(1,2), * pp ;Pixel * ppx ;

pp = new Pixel ( Pixel::BLANC, 4 , 8);

// autorisé, car on peut affecter à un pointeur de Point// l'adresse d'un objet d'une classe descendante// mais

pp->Colorer( ... ); // est interdit !! En effet pp reste un point !

ppx = &p; // de même, ceci est interdit !// ppx ->Colorer( Pixel :: ROUGE) ???

Page 31: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 31Département Informatique de l'INSA- Jean-Marc Pierson

• Le comportement du constructeur par recopie est différent selon que les constructeurs par recopie des classes de base (A) et dérivée (B) existent ou non.

• La classe dérivée (B) n'a pas de constructeur par recopie :– il y a donc appel au constructeur par recopie par défaut de B. Cela provoque

l'appel du constructeur par recopie de A. Si A n'a pas de constructeur par recopie, le constructeur par recopie par défaut est utilisé.

• La classe dérivée (B) a un constructeur par recopie :– si celui-ci fait appel au constructeur par recopie de A dans son en-tête (B(B& x):A(…) { }), alors celui-ci sera appelé. Sinon le constructeur sans

argument de A sera appelé.

Constructeur par recopie• Supposons que B hérite de A et considérons

l’affectation entre objets de type B.• Si B surcharge l’opérateur =, on ne fera appel qu’à

ce dernier.• Si B ne surcharge pas l’opérateur =, on fera appel à

l’opérateur = de A (surchargé ou par défaut) pour les attributs hérités de A et à l’affectation par défaut pour les autres.

Héritage et affectation

Affectation d'objets/* supposons que la classe Point soit munie d'un constructeur

Point (int abs, int ord) ;et que la classe Pixel qui hérite de Point ait un constructeur

Pixel (Couleur laCouleur, int abs, int ord) ; */

Point p (1,2) ;

Pixel px (Pixel::NOIR, 3, 5);p = px ; // autorisé, affectation partielle

// ici, c'est l'opérateur d'affectation de la classe Point qui est utilisé (surchargé ou par défaut) : le Pixel est converti enPoint, puis l'affectation se fait

Spécialisation par redéfinition de méthodesclass Point{ public : virtual void Afficher ()

{ cout << x <<"," << y <<endl ; }protected :

int x, y; // x et y sont visibles des classes descendantes};class Pixel : public Point { public :

virtual void Afficher () // redéfinition de afficher{ cout << x <<"," << y << "couleur:" << coul

<<endl ;}// on aurait pu réutiliser la méthode de l'ancêtre, avec le corps suivant :// { cout << "couleur:"<<coul<<" " ; // Point :: Afficher() ; }} ;

Page 32: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 32Département Informatique de l'INSA- Jean-Marc Pierson

Différence entre ...surcharge et redéfinition

• Surcharge : on définit une méthode ayant le même nom qu'une autre déjà définie (dans la même classe ou une classe parente) mais des paramètres différents

• Redéfinition : on définit une méthode ayant la même signature (nom+paramètres+code retour) qu'une méthode définie dans une classe parente

Liaison statique/dynamiquePoint * pt = new Point ( 3 , 5 ) ;

pt -> Afficher() ; // appel de la méthode Point :: Afficher()

pt = new Pixel ( ROUGE , 4 , 8) ;

pt -> Afficher () ; // appel de la méthode Pixel :: Afficher()

Si l'on n'avait pas déclaré la méthode Afficher virtual dans la classe de base, on aurait eu une liaison statique et donc un appel à Point::Afficher() au lieu de Pixel::Afficher().

Pour obtenir un lien dynamique, on doit mettre l'attribut virtual dans la déclaration de la méthode, dans l'interface de la classe de base :virtual typeRetour NomMéthode (listeParamètres) ;

// NomMethode ne peut être redéfinie dans les descendants // qu'avec la même liste de paramètres et le même type de retour

Danger de la liaison statiqueclass Point{ public :

...void Afficher() ;void Deplacer(int dx, int dy) {

x += dx ; y +=dy ; Afficher(); }

...} ;

class Pixel : public Point{ public : Pixel(Couleur, int, int);void Colorer (Couleur) ;void Afficher() ;

protected : Couleur c ;

} ;

Point p ( 1 , 5 ) ;Pixel px ( ROUGE , 4, 8 ) ;p . Afficher(); // affiche 1, 5px . Afficher(); // affiche 4, 8, couleur:rougep . Deplacer ( 1,1 ) ; // affiche 2, 6px . Deplacer( 1,1 ) ; // affiche 5, 9// car c'est la méthode Point :: Afficher qui a été appelée !!!// Remède : virtual void Afficher() dans Point

Le polymorphisme

• Concept de la théorie des types, selon lequel un nom d’objet peut désigner des instances de classes différentes issues d’une même arborescence

• Étroitement associé à l’interaction entre l’héritage et la liaison dynamique

• Une même opération peut se comporter différemment sur différentes classes issues de la même arborescence

Page 33: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 33Département Informatique de l'INSA- Jean-Marc Pierson

Le polymorphisme

class Instrument { …public:void off() {…}void play() {

cout << "Instrument.play()" << endl;}

};

class Wind : public Instrument { …public:void play() {

cout << "Wind.play()" << endl;}

};

void main() {Wind x;

((Instrument*)&x)->play();x.play();

}

Instrument *x=new Wind();x->play();

?

x est un instrument.

Ligature statique (Early binding)

Le polymorphisme

flûte est un instrument de musique à vent dont flûte est un Instrument.

L’appel à play considère le type réel de l’instrument (ici Wind) et fait donc appel à la fonction play de Wind.

Cette « recherche » est effectuée pour toute fonction redefinie et virtuelle.

class Instrument { …void off() {…}virtual void play() {

cout << "Instrument.play()" << endl;}

};

class Wind : public Instrument { …virtual void play() {

cout << "Wind.play()" << endl;}

};

void main() {Instrument *flute=new Wind();flute->play();

}

Ligature dynamique (Late binding)

Le polymorphisme• Techniquement, comment ça marche ?• Toute instance dispose d’une référence sur une table qui

associe le nom des fonctions et l’emplacement du code des fonctions.

• Il existe une table par classe.

void play(…) {…}Wind

void play(…) {…}Instrument

flûte…off

play...

Wind

void off(…) {…}Instrument

La fonction off n’est pas redéfinie.

• Il est conseillé de déclarer les destructeurs virtuels.

Destructeur et polymorphisme

class Instrument {...virtual ~Instrument() {...}

};

void main() {Instrument *flute=new Wind();

flute->play();delete flute;

}

1

2

class Wind : public Instrument { ...

virtual ~Wind() { ... }};

Page 34: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 34Département Informatique de l'INSA- Jean-Marc Pierson

Exemple de polymorphisme

Forme

Ligne RectangleCercle Dessin

virtual void Deplacer() ;virtual void Dessiner() const=0 ;

Ligne( ) ;virtual void Dessiner() const ;

Cercle() ;virtual void Dessiner() const ;

Rectangle() ;virtual void Dessiner()

const ;

/* un Dessin est une liste de Formes :structure de donnéespolymorphe*/Dessin() ;virtual void Deplacer();virtual void Dessiner()

const;void Ajouter(Forme *) ;

classe de base abstraite

Classes abstraitesLe seul but de certaines classes est de servir uniquement de classes

de base, et non d'être instanciables : on parle de

classes abstraites ( cas de Forme ci-dessus)En C++, une classe est considérée comme abstraite, si sa définition

contient une méthode virtuelle pure . Exemple, pour Forme,virtual void Dessiner() = 0 ;

==> le compilateur C++ interdit d'instancier la classe Formeet vérifie que tous ses descendants redéfinissent la méthode

virtual void Dessiner ()Une classe n'ayant que des méthodes virtuelles est une spécification

d'un type abstrait (TA) : noms et signatures des opérations imposés pour toutes les classes d'implémentation

Forme canonique d'une classe class X{ public : // méthodes publiques

// . . . . . . . . . . . // autres méthodes

X & operator = ( const X &) ; // affectation

X () ; // constructeur par défaut

X (const X &) ; // constructeur de copie

virtual ~X () ; // destructeur

private : . . . . . . // attributs privés de X

protected : . . . // attributs accessibles à X et à ses descendants

} ;

Création d'une classe simple par héritage d'un exemplaire de classe générique

On peut combiner héritage et généricité . Exemple :template <class T> // Point est une classe génériqueclass Point { public :

Point (T abs=0, T ord=0): x(abs),y(ord) {};void Afficher() ;

protected : T x,y ;

} ;class Pixel : public Point<int> // Pixel hérite de l'exemplaire Point<int>{ public :

Pixel (Couleur coul, int abs = 0 , int ord = 0): c(coul), Point <int> (abs,ord) {};

protected : Couleur c ;} ;

Page 35: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 35Département Informatique de l'INSA- Jean-Marc Pierson

Création d'une classe générique par héritage

On peut obtenir une classe générique par héritage d'une classeExemples :template <class T> // héritage d'une classe simple Bclass A : public B{

// . . .} ;

template <class T> // héritage d'une classe génériqueclass Vecteur : public Vect<T> {

// . . .} ;

L’héritage multiple

• En C++, l’héritage peut être multiple.

• Une instance de la classe C hérite à la fois des propriétés de A et des propriétés de B.

• Une instance de C pourra être vu comme un objet de type A et de type B.

A B

C

• Toutes les règles valables pour l’héritage simple sont valables pour l’héritage multiple.

• La déclaration de l’héritage multiple est de la forme : class C : public A, public B {…};

• Les constructeurs des super classes sont appelées dans l’ordre indiqué dans la déclaration de la sous-classe (ici celui de A puis celui de B).

• Si deux membres (données ou fonctions) appartenant respectivement à la classe A et à la classe B portent le même nom, la portée permettra d’en faire la différence dans la classe C (opérateur ::)

L’héritage multiple : généralitésL’héritage multiple : exemple

class A {public:int i;

};

class B {public:int i;

};

class C : public A, public B {public:void f();

};

void C::f() {i=5; // ambigu : erreur à la compilationA::i=5; // Ok, affectation de l’attribut i de la

// partie provenant de A.B::i=7; // Ok, affectation de l’attribut i de la

// partie provenant de B.}

Page 36: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 36Département Informatique de l'INSA- Jean-Marc Pierson

Héritage multiple et constructeurs

void main() {C objet_c;// appel des constructeurs B(), A() et C()

}

class A {public: A(int n=0) {}

};

class B {public:B(int n=0) {}

};

class C: public B, public A {public:

C(int i, int j):A(i),B(j) {} };

• Autre problème de l’héritage multiple : héritage multiple de la même classe.

• Par défaut, la classe D hérite deux fois de la classe A ce qui, dans la majorité des cas, n’a aucun intérêt : on parle alors d'héritage répété

Héritage multiple de la même classe :à éviter

B C

D

A

Héritage répété : exempleclass A {public:

virtual void m() {};};

class B : public A {};class C : public A {};

class D : public B, public C {};

À l'intérieur de la classe D, il y a héritage répété de la classe A; l'identificateur m qui en est hérité doit être explicitement qualifié B::m ou C::m . Dans D, il n'est pas possible de faire référence à m sans l'indicateur de portée ::

• Il est possible de limiter le nombre de présences d’une super classe dans une sous-classe en la déclarant virtualdans l’héritage : on parle d'héritage commun (à l'inverse de l'héritage répété par défaut)

Héritage commun

class A {…};

class B : public virtual A {…};

class C : public virtual A {…};

class D : public B, public C {…};

La classe D hérite une seule fois des membres de A.Attention : virtual est placé à l'héritage direct de A.

Page 37: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 37Département Informatique de l'INSA- Jean-Marc Pierson

class A {public:

virtual void m() {};};

class B : public virtual A {};class C : public virtual A {};

class D : public B, public C {};

À l'intérieur de la classe D, il y a héritage commun de la classe A; l'identificateur m est unique et peut être utilisé tel quel

Héritage commun : exemple Problème de l'héritage multipleclass A {public:

virtual void m() {};};

class B : public virtual A {};class C : public virtual A {

virtual void m() {}; // redéfinition de m};

class D : public B, public C {};

Dans la classe D, l'identificateur m peut-être soit celui de l'original (A::m), soit celui de C (C::m ). On peut utiliser l'identificateur m sans opérateur de portée : par défaut, c'est celui de C qui est utilisé

On n'hérite pas la terre de nos parents, nous l'empruntons à nos enfants

-- Léopold Sedar Senghor

"Programmation objet en C++"Plan

• introduction à la P . O . O, le C++ et le C• préprocesseur• types des données manipulables • classes/méthodes/fonctions• portée des noms/durée de vie des objets • fonctions ordinaires/bibliothèques• instructions• expressions/opérateurs• surcharge d'opérateurs • classes et fonctions génériques • héritage

• compléments : friend/conversions/exceptions• La librairie standard C++

Page 38: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 38Département Informatique de l'INSA- Jean-Marc Pierson

Fonctions et classes amies

• Pour permettre à une fonction d'accéder à des données privées d'une classe

• Principalement utilisé pour la surcharge d'opérateurs

• On peut aussi déclarer une classe entière comme étant amie : toutes ses méthodes pourront accéder à toutes les données

Utilisation des fonctions amiesclass Complex {public:Complex(int r=0, int i=0):re(r),im(i) {};

int re, im;};

Complex operator *(int k, Complex &c) {return Complex(k * c.re, k * c.im);

}

private: int re, im;

accès interdit !

Solution : fonctions amies

class Complex {public:Complex(int r=0, int i=0):re(r),im(i) {};friend Complex operator *(int k, Complex &c);private : int re, im;

};

Complex operator *(int k, Complex &c) {return Complex(k * c.re, k * c.im);

}

Classe amieclass Complex {

public:Complex(int r=0, int i=0):re(r),im(i) {};friend Affiche;

private : int re, im;

};

class Affiche {public:void print_complexe(Complex &c);

};

void Affiche::print_complexe(Complex &c) { cout << "Partie Réelle : " << c.re << endl;cout << "Partie Imaginaire : " << c.im << endl;

}

Toute la classe Affiche (et donc toutes ses méthodes) a un accès à la classe Complex

Page 39: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 39Département Informatique de l'INSA- Jean-Marc Pierson

Méthode amieclass Complex {public:

Complex(int r=0, int i=0):re(r),im(i) {};friend Affiche::print_complexe(Complex &c);

private : int re, im;

};

Seule la méthode print_complexe a un accès à la classe Complex

Compléments sur l'amitié• L'amitié n'est pas symétrique : si une classe A est amie d'une

classe B, alors B n'est pas forcément amie de A• L'amitié n'est pas transitive : les amis des amis ne sont pas des

amis ; si une classe A est amie d'une classe B, elle-même amie d'une classe C, alors A n'est pas amie de la classe C par défaut(mais on peut bien sûr la déclarer amie explicitement si on désire)

• L'amitié n'est pas héritée : si une classe A est amie d'une classe B et que la classe C est une classe fille de la classe B,alors A n'est pas amie de la classe C par défaut (mais on peut bien sûr la déclarer amie explicitement si on désire); par contre si D hérite de A, alors D est amie de B

• remarques valables pour les fonctions aussi : une fonction amie d'une classe A amie d'une classe B n'est pas amie de la classe B, ni des classes dérivées de A

Conversions de type implicites• automatiquement effectuées par le compilateur pour :

• l'évaluation d'une expression : 3/4.3 // l'entier 3 est converti en float• le passage de paramètres à une fonction :

void f(float a) { cout << a; };void main() {

int i = 4; f(i); // l'entier 4 est converti en float

}• l'affectation : int i; char c = i; // quelle valeur pour c ?

• entre types primitifs : – booléen -> entier (false/true -> 0/1)– entier ou pointeur -> booléen (nul/non nul -> false/true)– entier -> entier de taille supérieure (char -> short -> int-> long)– entier non signés -> entiers signés– enum -> int– entier -> float -> double

• entre objets de même type : pointeurs d'objets de classes liées par héritage

Les conversions de type explicites (à éviter)

• Conversion contrôlée par le compilateur : static_cast <type> (expression)

• Conversion contrôlée à l'exécution :dynamic_cast <type>(expression)

• Conversion sans contrôle :reinterpret_cast <type>(expression)

• Conversion "à la C"(type) expression : exemple : (float)3

Page 40: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 40Département Informatique de l'INSA- Jean-Marc Pierson

Conversions : d'une Classe vers un type T

• par la définition d'un opérateur unaire "operator T" qui renvoie une valeur de type T (type primitif ou une classe)class A { public :

A() { m_a = 10; }operator int (); // conversion d'un A en int

private: int m_a;};

void main() { A objet_A; int b = objet_A + 3;

}

A::operator int() { return m_a;}

Conversions : d'un type T vers une Classe• par la définition d'un constructeur qui convertit un objet de

type T (primitif ou classe) en objet de la classe A

class A { public :

A() { m_a = 10; }A(int &valeur) { m_a = valeur; }

private: int m_a;};

void main() { int b = 3;A objet_A = (A)b;A objet_A2 = b;A objet_A3 = A(b);A objet_A4(b);

}

Attention aux conversions implicites !class B { public :

void uneMethodeDeB(A objetA);

void main() { int c = 3;B oB;

oB.uneMethodeDeB( c );}

Ici, c est converti en instance de la classe A avant d'être passé

en paramètre à uneMethodeDeB()...

Moralité : éviter les constructeurs à un seul paramètre et ceux où seul le premier est obligatoireclass A { public :

A(int &valeur1, int &valeur2 = 1) { m_a = valeur + valeur2; }};

Conversions explicites définies par l'utilisateur

• si on ne veut pas que le constructeur précédent réalise une conversion implicite, il faut faire précéder la déclaration de explicit

class A { public :

A() { m_a = 10; }explicit A(int &valeur) { m_a = valeur; }

private: int m_a;};

void main() { int b = 3;A objet_A = (A)b;A objet_A2 = b; A objet_A3 = A(b);A objet_A4(b);

}

INTERDIT: la conversion doit être

explicite

Page 41: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 41Département Informatique de l'INSA- Jean-Marc Pierson

Les exceptions• Le programme idéal est un programme sans erreur !• Le compilateur est le premier niveau de contrôle des erreurs

dites de syntaxe, de type, voire de sémantique.• Le deuxième niveau de contrôle fait intervenir la notion

d’exception.• Lors du développement, on ne peut jamais savoir ce que

l’utilisateur de la classe ou du programme va faire :float inverse(float a) {

return 1/a; // si a = 0 ?}

Exceptions : principe• Si une fonction rencontre un problème qu'elle ne peut

pas traiter, elle lance ("throw") une exception en espérant que son appelant pourra le traiter en interceptant("catch") cette exception .

• Syntaxe :try{ // bloc pouvant "lancer" une exception par

throw exprException ;}catch (TypeException){ //gestionnaire des exceptions de type TypeException}

• Les exceptions permettent de séparer le bloc d'instructions de la gestion des erreurs pouvant survenir dans un bloc.

try {// Code pouvant lever des exceptions

}catch (type [[&]variable]){

// Gestion de l'exception}

Les exceptions

Le mot clé try indique que le code du bloc peut soulever des exceptions et que si c’est le cas alors il y aura exécution d’un bloc marqué par le mot clé catch.

Un bloc catch prend en paramètre un type quelconque (classe, par exemple). On peut en définissant plusieurs blocs catch prenant différents types d’exception réalise un traitementdifférent selon l’exception soulevée.

Exemple d'exceptions

#include <exception>

try {char *ptr = new char[1000000000];// ... suite en cas de succès de new (improbable ...)

}catch ( bad_alloc ) {

// en cas d'échec d'allocation mémoire par new// une exception bad_alloc est lancée par new

// traitement de l'erreur d'allocation}

Bibliothèque des exceptions prédéfinies

Page 42: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 42Département Informatique de l'INSA- Jean-Marc Pierson

Spécification d'exceptions (1/2)• L'appel à une méthode pouvant lever une exception doit :

– soit être contenu dans un bloc try/catchchar * alloue(int size){char *ptr;try {

char *ptr = new char[size];}catch (bad_alloc) {

cout << "Allocation impossible";

}return ptr;

}

Spécification d'exceptions (2/2)– soit être situé dans une méthode propageant (throw) cette

classe d'exception. La méthode ne traite pas l’exception mais laisse la méthode appelante traiter l’exception

char * alloue(int size) throw (bad_alloc) {char *ptr = new char[size];return ptr;

}

• de bloc en bloc : remontée dans l'appel des méthodes jusqu'à ce qu'un bloc catch acceptant cette exception soit trouvé.

• Si aucun bloc catch n'est trouvé, la fonction spéciale terminate() est appelée et le programme s'arrête. Il est possible de changer cette fonction à l'aide de la fonction set_terminate(maFonctionDeFin);

• Un bloc catch(...) intercepte toutes les exceptions.• On peut re-propager une exception depuis un bloc catch

avec throw;:l'exception est alors relancée au bloc englobant

Propagation des exceptionsNon propagation des exceptions

• On peut signifier qu'une fonction ne propage jamais une exception aux fonctions appelantes :

•void f() throw()

indique que la fonction f ne propage aucune exception.

• Par défaut, une méthode peut propager toutes les exceptions.

Page 43: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 43Département Informatique de l'INSA- Jean-Marc Pierson

• Les programmes peuvent aussi gérer des exceptions qui seront ensuite traiter par la méthode vue précédemment.

• La levée d’une exception passe par la création d’une instance d’une classe ou d'un type et l’utilisation du mot clé throw.

if(t == null)throw NullPointerException();

Throw : lancer des exceptionsclass Essai { public :

class Erreur { };void f1() { throw Erreur(); }

};

void main() {try {

Essai e1;e1.f1();

}catch ( Essai::Erreur ) {

cout << "interception de Erreur" << endl;}

}

Exemple d'exception

class Essai { public :

class Erreur { public: string getMessage()

{ return "Errare humanum est"; }};void f1() { throw Erreur(); }

};

void main() {try {

Essai e1;e1.f1();

}catch ( Essai::Erreur & e) {

cout << e.getMessage() << endl;}

}

Exemple d'exception

• Si une exception est levée dans une fonction ou méthode ne propageant pas l'exception alors la fonction unexcepted() est appelée et le programme est arrêté (par défaut cette fonction fait appel à terminate() )

• On peut définir sa propre fonction unexpected() par un appel à la fonction set_unexpected(maFonctionInattendue);

Exceptions inattendue

Page 44: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 44Département Informatique de l'INSA- Jean-Marc Pierson

Exemple d'exception inattendue#include <iostream.h>

void my_unexpected() {cout << "my_unexpected" << endl;exit(1);

}class Erreur {};class Toto {};class Essai {

public:void f1() throw (Erreur);

};

void Essai::f1() throw (Erreur) {

throw Toto();}

void main() {set_unexpected(& my_unexpected);try {

Essai e1;e1.f1();

}catch ( Erreur ) {// gère l'Erreur : jamais appelé ici ! }

}

Hiérarchie d'exception et ordre d'interception

• Lorsque plusieurs gestionnaires d'exceptions sont précisés, on les essaie dans l'ordre d'apparition dans le code

• Suite au lancement d'une exception de classe T, le gestionnaire activé est celui qui intercepte : – le type T– soit une classe dont T est un descendant par héritage

public– un type pointeur dans lequel T (supposé être un

pointeur) peut être converti

Exemple de hiérarchie d'exceptionsclass ErreurMath {};class Depassement : public ErreurMath {};class DivisionParZero : public ErreurMath {};// ...try { // du code sensé lever une exception mathématique}catch (DivisionParZero) {

// gère l'exception DivisionParZero (et toutes ses descendantes)}catch (ErreurMath) {

// gère toutes les autres exceptions sous classe de ErreurMath}

Page 45: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 45Département Informatique de l'INSA- Jean-Marc Pierson

Constructeurs et exceptions

• Les constructeurs ne renvoient pas de valeurs : les exceptions peuvent être un moyen de signifier des erreurs à la construction d'un objet : l'objet n'est alors pas construit, et il n'y a pas appel au destructeur !

Exemple de Constructeurs avec Exceptionclass A {

public:A(string & mess) throw (int) {

cout << "constructeur" << endl;tableau = new char[10];throw 2;

pointeur = new int; // jamais exécuté}

~A() { cout << "destructeur jamais appelé !" << endl; }private:

char [] tableau; int *pointeur;};void main() {

try { A a = new A("coucou"); }catch (...) { cout << "Erreur construction" << endl;}

}L'opérateur delete est appelé sur l'objet, mais pas le destructeur

Exemple de Constructeurs avec Exceptionclass A {

public:A(string & mess) throw (int)

try {message = NULL; pointeur = NULL;cout << "constructeur" << endl;tableau = new char[10];throw 2;

pointeur = new int; // jamais exécuté}catch (int) {

delete [] tableau; delete pointeur;

}

~A() { cout << "destructeur" << endl; }private: char [] tableau; int *pointeur;

};

Combinaison Constructeurs/Héritage/Exceptionclass B : public A, public C {

public:B(string & mess) throw (int)

try : A(mess), C(mess) {cout << "constructeur" << endl;throw 2;

}catch (int) {

message = mess;}

~A() { cout << "destructeur" << endl; }private: string message;

};

Les appels aux constructeurs de A et C peuvent lancer des exceptions : ces exceptions, même si elles sont traitées dans A ou C sont renvoyées vers B (contrairement à d'habitude); aucun objet n'est créé

Page 46: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 46Département Informatique de l'INSA- Jean-Marc Pierson

Compléments sur les exceptions

• La clause throw n'intervient pas dans la signature d'une méthode (pour la surcharge et la redéfinition)

• pour les méthodes const, on la met après le const

• pour les méthodes virtuelles pures (=0), on la met avant le =0

exemple : void f() const throw (int) = 0;

Les flux d’E/S• Un flux, appelé stream en C++, est un périphérique logique

qui produit ou consomme des informations.• Un stream représente un flot de données entre une source

(producteur) et une cible (consommateur).• Pour utiliser un stream, il faut inclure le ou les fichiers

suivants :– iostream : flux standards (cout, cin, cerr…)– fstream : fichier– strstream : chaîne de caractères vu comme un flux– iomanip : pour utiliser les manipulateurs

• Il existe 4 flux standards :– cin : saisie clavier– cout : sortie écran– cerr : sortie écran pour l’affichage des erreurs– clog : sortie bufférisée écran

• Ces 4 flux peuvent être redirigés (cerr vers un fichier, par exemple).

Les flux standards• Toutes les classes gérant des flux possède un objet de la

classe streambuf qui est une représentation du bufferdans lequel on lit ou écrit : on le récupère avec la méthode rdbuf()

• Toutes les entrées-sorties sont bufferisées : on peut changer le buffer (et donc sa taille) avec la méthode pubsetbuf(char *newbuf, int taille)

• La classe ios ancêtre des toutes les classes de type stream gère l’accès au buffer : c'est l'équivalent de la classe basic_ios<char>

• De même, par exemple, la classe istream est la classe basic_istream<char>

La hiérarchie des classes

Page 47: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 47Département Informatique de l'INSA- Jean-Marc Pierson

La hiérarchie des classes d'entrée/sorties

• A chaque flux est associé un vecteur de bits formant le statut d’erreur :– eofbit : activé si la fin du fichier a été atteinte c-à-d si le flux

n’a plus aucun caractère disponible– failbit : activé si la dernière opération d’E/S a échoué– badbit : activé si la dernière opération d’E/S est invalide– hardfail : activé si le flux est dans un état d’erreur

irrécupérable

• L’accès aux bits d’erreur se fait par l’intermédiaire de 4 fonctions membres : eof(), bad(), fail() etgood().

• La fonction good() retourne vrai (1) s’il y a aucune erreur.

L'état des flux

Exemple d'utilisationint x = 1;char ch1;do {

cout << "Entrer un nombre :" << endl;cin >> x;

if (cin.fail()) { cin.clear(); // on efface les bits de statuscin >> ch1;cout << "Valeur incorrect entrée";

}else cout << "Le nombre lu est " << x <<

endl;} while (x != 0);

• L’opérateur () est redéfini de manière à ce que si fl désigne un flux alors (fl) prenne une valeur non nulle si aucun des bits d’erreur n’est activé et prenne une valeur nulle dans le cas contraire.

if (fl) … <==> if (!fl.good()) …

• L’opérateur ! est redéfini de manière à ce que si fl désigne un flux alors !fl prenne une valeur nulle si un des bits d’erreur est activé et prenne une valeur non nulle dans le cas contraire.

Fonctions et opérateurs sur flux

Page 48: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 48Département Informatique de l'INSA- Jean-Marc Pierson

• L’écriture dans un stream s’effectue à l’aide de l’opérateur << :

ostream& operator<<(…);Le type de retour permet d’utiliser l’opérateur << en cascade.

((cout << "hello") << "world");

• La lecture dans un stream s’effectue à l’aide de l’opérateur >> :

istream& operator>>(…);

• Les opérateurs << et >> sont définis pour tous les types primitifs.

Les opérateurs << et >>

• Si vous désirez que les instances de vos classes puisse s’afficher à l’écran ou s’enregistrer dans un fichier, il faut surcharger l’opérateur <<.

• Il ne peut être écrit qu’en dehors d’une classe stream (on ne peut pas modifier le code d’une classe des librairies standards !) et évidemment en dehors de vos classes (car le premier opérande est un stream !).

• Il faut donc définir l’opérateur << à l’extérieur de vos classes et en général ami de vos classes afin d’avoir accès à leurs membres : si l'opérateur << n'est pas ami, il ne peut avoir accès aux donnéesprivées de A

Redéfinition de << (ou >>)

Exemple de redéfinition de <<class A {

private :int m_a;

public :A(int p_a):m_a(p_a) { }

friend ostream& operator<<(ostream &, A const &);};

ostream& operator<<(ostream& o,A const & a){

o << a.m_a;return o;

}

void main(){

A a(9);cout << A << endl;

}

• En plus de l'opérateur <<, la classe ostream contient les méthodes suivantes :– ostream & put(char c); : insère un caractère dans le flux.– ostream & write(const char *, int n); : insère n caractères

dans le flux.– streampos tellp(); : retourne la position courante dans le flux.– ostream & seekp(streampos n); : se positionne à n octet(s) par

rapport au début du flux. Les positions dans un flux commencent à 0 et le type streampos correspond à la position d'un caractère dans le flux.

– ostream & seekp(streamoff dep, seek_dir dir); : se positionne à dep octet(s) par rapport :

• au début du flot : dir = beg • à la position courante : dir = cur • à la fin du flot : dir = end (et dep est négatif!)

– ostream & flush(); : vide les tampons du flux.

Méthode des flux de sortie

Page 49: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 49Département Informatique de l'INSA- Jean-Marc Pierson

Exemple d'utilisationvoid main()

{

cout << "Quelques essais sur les flux" << endl ;

// Rouge : suite de char faisant passer un terminal ANSI à // la couleur rouge pour l'écritureconst char Rouge[] = { 033, '[' , '3', '1', 'm' };cout.write( Rouge, sizeof(Rouge));cout << "Ecriture en rouge" << endl;

const char Reset[] = {033, '[', 'm', 017};cout.write( Reset, sizeof(Reset));cout << "Retour à la normale" << endl;

}

Exécution :Quelques essais sur les flux

Ecriture en rougeRetour à la normale

• En plus de l'opérateur >>, la classe istream contient les méthodes suivantes :– int get(); : retourne la valeur du caractère lu (ou EOF si fin)– istream & get(char &c); : extrait le premier caractère du flux

et le place dans c. – int peek(); : lecture non destructrice du caractère suivant– istream & get(char *ch, int n, char delim='\n'); :

extrait n -1 caractères du flux et les placent à partir de l'adresse ch. La lecture s'arrête avant le délimiteur delim

– istream & getline(char *ch, int n, char delim='\n');: comme la méthode précédente sauf que le délimiteur est extraitdu flux mais n'est pas recopié dans le tampon.

Méthode des flux d'entrée

– istream & read(char *ch, int n); : extrait un bloc d' au plus n octets du flux et les place à l'adresse ch. Le nombre d'octetseffectivement lus peut être obtenu par la méthode gcount().

– int gcount(); : retourne le nombre de caractères non formatés extraits lors de la dernière lecture

– streampos tellg(); : retourne la position courante dans le flux.– istream & seekg(streampos n); : se positionne à n octet(s) par

rapport au début du flux. Les positions dans un flot commencent à 0 et le type streampos correspond à la position d'un caractère dans le flux.

– istream & seekg(streamoff dep, seek_dir dir); : se positionne à dep octet(s) par rapport au début du flux, à la position courante ou à la fin du flux.

Méthode des flux d'entrée (suite) • La manipulation des fichiers est rendu possible grâce à deux classes : ifstream et ofstream.

• Définies dans <fstream>• L'ouverture d'un flux de type fichier est réalisé par le

constructeur.ifstream f("toto.txt");ofstream f("toto.txt", ios::app |

ios::nocreate);

• ou alors par l'appel à la méthode open( ... )fstream f3;

f3.open("toto.txt", ios::in | ios::out);

• fermeture par la méthode close()

Les fichiers : des streams particuliers

Page 50: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 50Département Informatique de l'INSA- Jean-Marc Pierson

MODE

D'OUVERTURE

Exemple d'utilisation

void main()

{

cout << "Quelques essais sur les flux" << endl ;

// on se positionne à la fin du fichierifstream f("essai.txt", ios::ate);

cout << "Taille du fichier en octets = ";

// on regarde où on est

cout << f.tellg() << endl;

}

Les chaînes de caractères vues comme des flux

• On peut associer un flux de caractère à une chaîne : les opérations définies sur les stream deviennent valables

• C'est la classe strstream (ou sstream)• Définies dans <strstream> (ou

<sstream>)• Un buffer particulier est utilisé : stringbuf

Exemple d'utilisation// création d'un objet strstream en lecture/écriture par défautstrstream inout;

// écriture de 2 lignes sur ce fluxinout << "C'est l'histoire d'un homme" << endl

<< "This is the story of a man." << endl;char line [80];

// extract the first lineinout.getline (line, sizeof line);

// output the first line to stdoutcout << "Français: " << line << endl;

// extract the second lineinout.getline (line, sizeof line);cout << "English:" << line << endl;

// output the contents of the stream object to stdoutcout << endl << inout.str () << endl;

Page 51: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 51Département Informatique de l'INSA- Jean-Marc Pierson

• Il existe au niveau de la classe ios plusieurs champs utilisés pour le formatage des entrées-sorties :– precision : précision pour la sortie des réels (float ou double)– width : longueur du champ de sortie– fill : caractère de remplissage des champs de sortie lorsque le

champ est plus grand que l’information– flags : définition du format

• Ces différents champs sont accessibles via des fonctions membres (setf, unsetf, width, precision et fill).

• Les deux premières fonctions permettent de préciser les flags de formatage.

Formatage Flags

de

formatage

Formatage

formatage

Page 52: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 52Département Informatique de l'INSA- Jean-Marc Pierson

Formatage : les fonctions de manipulation

Formatage : exempledouble f = 0.123456789;cout.fill('*');cout.precision(3); // 6 par défautcout.setf(ios::showpos | ios::scientific | ios::right);cout << "Valeur de f : |" ;cout.width(20); // le prochain champ affiché sera sur 20 caractèrescout << f << "|" << endl;cout.unsetf(ios::right);cout.setf(ios::left | ios::fixed);cout << "Valeur de f : |";cout.width(20);cout << f << "|" << endl;

Exécution :Valeur de f : |**********+1.234e-01|

Valeur de f : |+0.123**************|

Formatage : exemple n°2ifstream fic;

ofstream fic2;

char c;

fic.setf(ios::skipws);

fic.open("test.txt");

fic2.setf(ios::skipws);

fic2.open("test2.txt");

while (!fic.eof())

{

fic >> c;

fic2.put(c);

}

fic.close();

fic2.close();

En sortie,le fichier test2.txt est le fichier test.txt, sans les blancs (est blanc un caractère pour qui la fonction isspace() renvoie vrai)

Les manipulateurs

• Les manipulateurs sont des fonctions qui agissent sur les formats d’entrées/sorties.

• Evitent de se servir de setf et unsetf• Elles nécessitent l’inclusion de iomanip• Le plus connu est endl (retour chariot + retour à la

ligne) mais il en existe d’autres.• Ne s'appliquent que sur l'opération qui suit (sauf

certaines qui s'appliquent globalement)

Page 53: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 53Département Informatique de l'INSA- Jean-Marc Pierson

Les manipulateurs sans arguments

Il faut ajouter :* ws (ignorer les espaces en entrée)* dec,hex,oct* flush* endl, ends

cout << hex << 17 << endl;

Les manipulateurs sans arguments (suite)

• Comment écrire un manipulateur sans argument ?1) surcharge de l’opérateur << comme suit :ostream& operator<< (ostream&,

ostream& (*pf)(ostream&));

2) écrire une fonction prenant comme paramètre un streamet retournant une référence sur un stream.

Ses propres manipulateurs ?

ostream& toto(ostream& o){

o << "MANIPULATEUR";return o;

}

cout << "abc : " << toto <<endl;

Exécution :abc : MANIPULATEUR

Les manipulateurs avec arguments

cout << "|";cout << setw(10) << "bonjour";cout << "|";

Exécution :|bonjour |

Page 54: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 54Département Informatique de l'INSA- Jean-Marc Pierson

• Comment écrire un manipulateur avec arguments ?1) écrire une fonction prenant en paramètre un stream et

les arguments souhaité, et retournant une référence sur un stream.

ostream& manip(ostream& o,int i) {o << "MANIPULATEUR AVEC PARAMETRE = " << i;return o;

}

2) redéfinition de l’opérateur << (ou >>)ostream& operator<<(ostream& o,

NewManipulator m){ return m.pf(o,m.i); }

Ses propres manipulateurs ?3) écrire la classe NewManipulatortypedef ostream& (*t_pf)(ostream&,int);

// pointeur vers une fonction qui admet un stream et un entier en // paramètres et qui retourne une référence sur stream

class NewManipulator {int i;t_pf pf;public:

NewManipulator(t_pf p_pf, int x):pf(p_pf),i(x) { }

};

4) écrire une fonction (ce sera le manipulateur) qui prend un entier en paramètre et qui renvoie un NewManipulateurNewManipulator appelManipulateur(int i) {

return NewManipulator(manip,i); }

Les manipulateurs avec arguments

Manipulateurs avec arguments (fin)

• Utilisation : cout << appelManipulateur(3) << endl;

• Exécution :MANIPULATEUR AVEC PARAMETRE = 3

Pièges du C / C++

• Pièges syntaxiques– une erreur de syntaxe dans l'écriture d'une

expression C/C++ : la plupart sont détectées à la compilation

• Pièges sémantiques– une méconnaissance du langage entraîne des

erreurs difficilement détectables : le compilateur compile sans problème, mais le comportement n'est pas celui attendu

• Performances médiocres ...

Page 55: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 55Département Informatique de l'INSA- Jean-Marc Pierson

• if ( 0 < a < 5)// expression booléenne toujours vraie

• if (a=b)// vraie si b est différent de 0

• int numbers[] = {

001, // on aligne les nombres. Mais ...

010, // 8 pas 10, expression évaluée en octal !

014 }; // 12, pas 14

Quelques erreurs communes en C• int thisIsNuts[4], i; for ( i = 0; i < 10; ++i ) { thisIsNuts[ i ] = 0; }

• int i = 1;

printf("%d, %d, %d\n", i++, i++, i * i);

• int i = 1;

i/++i

• appelDeFonction(pointeur->membre, pointeur=&buffer);

• char *f() { char result[80]; sprintf(result,"anything will do"); return(result); }

int g() { char *p; p = f(); cout << "f() returns:" << p << endl; }

• maFonction,(arg1,arg2,arg3);

• switch (a) {

int var = 1; // jamais exécutécase A: ...

case B: ...

}

• switch (a) {

case A: ...

case B: ...

defaut : // jamais exécuté}

Page 56: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 56Département Informatique de l'INSA- Jean-Marc Pierson

• int maFonction (a) {

if (a) return(1);

}

• #define maximum(a,b) (a>b?a:b)

maximum(i++, j); // s'évalue en i++>j?i++:j

maximum(i=1,j=2); // s'évalue en i=1>j=2?i=1:j=2

Quelques erreurs en C++• int main() {

string a("Hello");string b(); // constructeur par défaut ? : non !...return 0;

}

• int n;while (!cin.eof()) {

cin >> n; // et si on entre abcd ?}

template<typename T> class Array { public:

Array(int size); T& operator[](int); Array<T>& operator=(const Array<T>&);

};

int main() {

Array<double> a(10);

a[0] = 0; a[1] = 1; a[2] = 4;

a[3] = 9; a[4] = 16; a = 36;

a = 36; a[7] = 49; a[8] = 64;

}

class Point {

public:

Point(double x = 0, double y = 0);

private:

double _x, _y;

};

int main() {

double a, r, x, y;

Point p = (x + r * cos(a), y + r * sin(a));

return 0;

}

Page 57: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 57Département Informatique de l'INSA- Jean-Marc Pierson

template<typename T> class Array { public: explicit Array(int size); private:

T* _data; int _size;

}; template<typename T> Array<T>::Array(intsize) : _size(size), _data(new T(size)) {}

int main() { Array<double> a(10); a[1] = 64; // le programme plante: pourquoi ?

}

template<typename T> class Array { public: explicit Array(int size); private:

T* _data; int _capacity;int _size;

}; template<typename T> Array<T>::Array(intsize) : _size(size),

_capacity(_size+10),_data(new T[_capacity]) {}

int main() { Array<double> a(100); // le programme plante: pourquoi ?

}

class Chaine {public :

Chaine(); // constructeur par défautChaine( const char * ch); // copie de ch dans bufferoperator = (Chaine & c); // copie de c.ch dans buffer

private : char * buffer;}class Name {

public: Name (const char * t) { name = t; }private : Chaine name;

}

int main() {Name a = "Joe";

}

// combien d'appel de création, de copie et de destruction ?1 - appel de Name::Name("Joe");2 - construction de Name::name, par défaut : 1 new3 - Chaine temporaire créée à partir de "Joe" : 1 new + 1 copie4 - Appel à l'opérateur = de la classe Chaine : 1 copie5 - le 4) entraîne la destruction de Name::name créé à l'étape 2,

puis un nouveau new puis la copie6 - le temporaire créé en 3) est détruit

Total : 3 new, 3 copies, 2 delete

class Chaine {public :

Chaine(); // constructeur par défautChaine( const char * ch); // copie de ch dans bufferoperator = (Chaine & c); // copie de c.ch dans buffer

private : char * buffer;}class Name {public: Name (const char * t):name(t); }private : Chaine name;

}int main() {Name a = "Joe";

}

// combien d'appel de création, de copie et de destruction ?1 - appel de Name::Name("Joe");2 - appel au constructeur de Chaine qui

correspond : 1 new + 1 copie

Page 58: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 58Département Informatique de l'INSA- Jean-Marc Pierson

class Shape {

public:

Shape() { reset(); }

private:

virtual void reset();

Color _color;

};

void Shape::reset() {

_color = BLACK;

}

class Point : public Shape {

public:

// pas de constructeur

virtual void reset();

private:

double _x, _y;

};

void Point::reset() {

Shape::reset();

_x = 0; _y = 0;

}

int main() {

Point p; // _color, _x, _y = ?

}

class Shape { //classe

// abstraite

public:

Shape() { init(); }

private:

void init() { reset(); }

virtual void reset()=0;

Color _color;

};

class Point : public Shape {

public:

// pas de constructeur

virtual void reset();

private:

double _x, _y;

};

void Point::reset() {

_x = 0; _y = 0;

}

int main() {

Point p; // le programme plante. Pourquoi ?

}

class A {public:

virtual void f(string s = "Base") {cout << "Classe de Base" << s << endl;

}}

class B : A {public:

virtual void f(string s = "Derived") {cout << "Classe dérivée : " << s << endl;

}}

int main() {B *b = new B;b->f(); // affiche : Classe dérivée : DerivedA *a = b;a->f(); // affiche : Classe dérivée : Base

}

class Employee {public:Employee(string name);virtual void print();

private:string _name;

};

class Mngr : public Employee {public:Mngr( string name,

string dept);virtual void print();

private:string _dept;

};

int main() { Employee* staff[10];staff[0] = new Employee("Harry Hacker");staff[1] = new Mngr("Joe Smith", "Sales");for (int i = 0; i < 10; i++) staff[i]->print();for (int i = 0; i < 10; i++) delete staff[i];

// de la mémoire n'est pas libérée : où ?}

Page 59: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 59Département Informatique de l'INSA- Jean-Marc Pierson

class Employee {public:Employee(string name);virtual ~Employee();

private:string _name;

};Employee::~Employee {

delete _name;}

class Mngr : public Employee {public:Mngr(string n, string sn):Employee(n), _secretary(new Employee(sn))

{};~Mngr();

private:Employee* _secretary;

};Mngr::~Mngr() {

delete _secretary;}

int main() {

Mngr m1 = Mngr("Sally Smith", "Joe Barnes");

Mngr m2 = m1;

} // problème à la destruction des deux Mngr

Quelques liens

• C Traps and Pitfalls, A. Koenig (http://www.programmersheaven.com/zone3/cat36/391.htm)

• http://www.michaelmoser.org/cppitfalls.htm• http://www.horstmann.com/cpp/pitfalls.html

While many languages let you shoot yourselfin the foot, C gives you a shotgun and lets you shoot yourself in the head.

-- Matt Spong (GNU C/C++ developper)

C et C++• Différences syntaxiques : des mêmes choses

s'écrivent différemment : (ex: les commentaires, le typedef devant les structures)

• Différences conceptuels : – C n'est pas un langage objet : pas de classes,

seulement des fonctions; pas de redéfinition de méthodes, pas de surcharge d'opérateur

– Pas de références : passage des paramètres aux fonctions par valeur ou par adresse

– Typage moins fort qu'en C++

Page 60: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 60Département Informatique de l'INSA- Jean-Marc Pierson

Name mangling en C++• Pour la production des fichiers objets, à la

compilation, transformation des noms de fonctions pour faire apparaître la signature dans le nom– exemple : long abs(long arg);

sera transformé (par exemple) en : abs_long• Deux signatures -> deux noms internes différents• Rappel : signature = nom+arguments (pas retour)

Coexistence C / C++

• En C, ce mécanisme n'est pas utile : les fichiers objets produits pour le C (et les bibliothèques qui les contiennent) contiennent seulement le symbole du nom de la fonction (abs dans l'exemple)

• Il faut indiquer au compilateur C++ que certaines fonctions sont "C" alors que d'autres sont "C++", afin qu'il retrouve les symboles internes correspondants : le mot clé extern

#include <stdio.h>#include <toto.h>void f(void) {

printf("Hello de f");}

Fichier toto.c

Fichier toto.o

gcc -c toto.c

extern "C" void f(void);

Fichier toto.h

#include <iostream>#include <titi.h>void g(void) {

cout<< "Hello de g" <<endl;}

Fichier titi.cpp

Fichier titi.og++ -c titi.cpp

extern "C++" void g(void);

Fichier titi.h

#include <toto.h>#include <titi.h>void main(void) {

f();g();

}

g++ -c main.cpp

Fichier main.cpp

Fichier main.o

Liaison : (production de l'exécutable)g++ -o affiche main.o toto.o titi.o

Coexistence avec extern

• Dans l'exemple, si on n'avait pas mis extern"C" dans toto.h, alors le compilateur C++ aurait créé un symbole interne "à la C++", au lieu de le créer "à la C" : à la liaison, il n'aurait pas été reconnu !

• Par défaut (si on ne met pas extern), le compilateur C++ ajoute extern "C++"

Page 61: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 61Département Informatique de l'INSA- Jean-Marc Pierson

Compilation conditionnelle• Ajout de :#ifdef __cplusplusextern "C" void f( void );

#elsevoid f( void );

#endif

ou alors #ifdef __cplusplus

extern "C" { #endif

void f(void);void f2(int, int);...

#ifdef __cplusplus}

#endif

Déclaration des fonctions en C et C++

int f( );

• En C, cette déclaration implique que la fonction f accepte un nombre quelconque d'arguments, de n'importe quels types

• En C++, cette déclaration implique que la fonction f n'a pas d'arguments : elle est équivalente à int f(void);

Déclaration implicite ?

int f( ) {g(); // fonction non déclarée avant

}

• En C, cette déclaration est légale : elle implique une déclaration implicite de la fonction g comme suit : extern int g();

• En C++, cette déclaration est illégale : il aurait du y avoir une déclaration de la fonction g avant

Liaison interne/externeconst int i = 10;

• En C, cette déclaration entraîne que la variable i est visible depuis tous les fichiers objets : portée globale, la liaison est externe par défaut; pour la rendre locale, on rajoute le mot clé static :static const int i = 10;

• En C++, elle n'est visible que dans le fichier objet où elle est déclarée (liaison interne); pour la rendre globale, on rajoute le mot clé extern :extern const int i = 10;

Page 62: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 62Département Informatique de l'INSA- Jean-Marc Pierson

Utilisation d'une variable globale

extern const int i = 10;Fichier toto.c

#include <iostream>

extern const int i; // indique que la constante i a été déclarée ailleurs

void main( void ) {cout << i = " << i << endl;

}

Fichier main.cpp

Initialisation des static

static int i = 10 + 20;

• en C, on ne peut initialiser qu'avec des constantes

static int i = 10 + f();

• en C++, on peut initialiser avec des fonctions

Gestion de la mémoire

• En C : – void * malloc( size_t );– void free ( void * );

• En C++ : – new ou new[ int ]– delete ou delete []

#include <malloc.h>

void main( void ) {int * buffer;buffer = malloc(10*sizeof(int));free ( buffer);

}

void main( void ) {int * buffer;buffer = new int[10]; delete [] buffer;

}

Meilleur contrôle des types, meilleure extensibilité et efficacité

Transtypage void *

void main( void ) {int * buffer;buffer = malloc(10*sizeof(int));

• ok en C, pas en C++ : la fonction malloc() renvoie un void *, pas un int *

• pour que ce soit valide (en C et C++), il aurait fallu écrire : buffer = (int *) malloc(10*sizeof(int));

Page 63: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 63Département Informatique de l'INSA- Jean-Marc Pierson

Conversion de type en C• Il n'existe que l'opérateur (type) :

– (float) 3 transforme l'entier 3 en 3.0

• Impossible d'utiliser float(3) • Pas de conversion avec static_cast, const_cast, ...• En C, les littéraux (ex: 'a') sont de type int : sizeof('a') == sizeof(int) == 4

• En C++, les littéraux (ex: 'a') sont de type char : sizeof('a') == sizeof(char) == 1

• Mais en C++ comme en C, ils sont converti en int lorsqu'ils apparaissent dans une expression

Gestion des fichiers en C• En C, les flux sont de types FILE *• Les flux standards sont stdout, stderr, stdin.• Les flux se manipulent avec les fonctions C fopen(),

fclose(), fprintf(), ...{char *s = "toto";int i = 3;FILE * fic = fopen ("toto.txt", "w");fprintf(fic, "%s %d", s, i);fclose(fic);

}

• La fonction printf(...) est en fait un fprintf(stdout, ...)

Format d'affichage en C

• "%d" : la valeur est interprétée comme un entier, affiché en décimal

• "%5d" : un champ de 5 caractères est réservé pour afficher l'entier : justification à droite

• "%-5d" : pareil sauf : justification à gauche • "%x" : la valeur est interprétée comme un entier, affiché en

haxadécimal• "%u" : la valeur est interprétée comme un entier non signé

(unsigned)• "%s" : la valeur est interprétée comme une chaîne de caractère

(tableau de caractère terminé par \0)• "%f" : la valeur est interprétée comme un float• "%5.2f" : la valeur est interprétée comme un float : affichage

de 5 chiffres significatifs, dont 2 après la virgule

Gestion des fichiers{char *s = "toto";int i = 3;printf(fic, "%s %s\n" s, i);fclose(fic);

}

• Ce programme plantera probablement : essai d'affichage d'une chaîne de caractère de l'adresse 3 !

• En C++, pas d'erreurs possibles{char *s = "toto";int i = 3;cout << s << " " << i << endl;

}

Page 64: Langage algorithmique (LA) Plan du coursJean-Marc.Pierson/coursC++.pdfDépartement Informatique de l'INSA- Jean-Marc Pierson Programmation objet en langage C++ 1 Langage C++ - Jean-Marc

Programmation objet en langage C++ 64Département Informatique de l'INSA- Jean-Marc Pierson

C++ et Java• C++ n'est pas un langage tout objet, puisqu'il y a

une coexistence entre C et C++• Java s'en rapproche... L'utilisateur ne peut pas

créér des fonctions : ce doit être des méthodes définies dans des classes

• Principales différences :– toutes les classes en Java héritent de la classe Objet– seulement l'héritage simple est défini– pas de pointeurs en Java : notion de références sur les

objets– test de type beaucoup plus complet (Boolean est

different de int !)

C++ et Java (suite)Principales différences (suite)

– les types primitifs ont une taille fixe quelque soit la plate forme de déploiement

– pas de surcharge d'opérateurs– gestion complète des exceptions– pas de fichiers d'inclusions, mais plutôt une

importation de fonctionnalités

• Le code Java compilé est interprété par une JVM afin d'être exécuté

Lire la fin d'un roman policier avant d'y arriver, c'est comme de manger un biscuit fourré à la noix de coco en allant tout de suite à la noix de coco : après il ne reste plus qu'à jeter le biscuit.

----- La ligne verte---- Stephen King