Download - Cours Math c++ fr
-
8/18/2019 Cours Math c++ fr
1/43
L C++
L J
M 2 2
-
8/18/2019 Cours Math c++ fr
2/43
2
-
8/18/2019 Cours Math c++ fr
3/43
i L'écriture utilisée pour travailler sur des instances d'objet est souvent lourdeet peu lisible. En C++, les opérateurs classiques peuvent être redéfinis.
Exemple
Complex a;
cout
-
8/18/2019 Cours Math c++ fr
4/43
Règles générales de surcharge d’opérateurs
Deux règles fondamentales régissent la surcharge des opérateurs unaires
ou binaires :
•si un opérateur est membre d'une classe, son premier opérandeest toujours du type de la classe à laquelle il appartient.
4
•quand un opérateur n'est pas membre d'une classe, au moins unde ses opérandes doit être de type classe.
-
8/18/2019 Cours Math c++ fr
5/43
A
h Lorsque les données membres d'une classe contiennent des pointeurs sur
des variables dynamiques, il est indispensable de redéfinir l'opérateur
d'affectation =
h Il est judicieux de passer l'unique paramètre en référence constante pour ne
pas risquer de le modifier.
Exemple :
class CPlx
5
….public:CPlx operator = (const CPlx &);
}
CPlx CPlx ::operator = (const CPlx & x){
re = x.re; im = x.im;return (*this);
}
void main (void){
CPlx x1, x2, x3, x4(4,4);...
x1 = x2 = x3 = x4;}
-
8/18/2019 Cours Math c++ fr
6/43
Exemple :
class CTab{
private:double t[TMAX];
public:double& operator [] (int);
} ;double& CTab::operator [] (int i)
6
{ if ( (i < 0) || (i > TMAX-1) ){cerr
-
8/18/2019 Cours Math c++ fr
7/43
h Cet opérateur est déjà utilisé pour tous les affichage de types prédéfinis
(entier, réel, chaine de caractère). En le surchargeant on peut gérer
l'affichage de n'importe quelle classe.
h Sa syntaxe est assez particulière par rapport aux autres opérateurs :
Exemple :
#include
using namespace std;
ostream& operator
-
8/18/2019 Cours Math c++ fr
8/43
h Cet opérateur est utilisé pour tous les saisies de types prédéfinis (entier,
réel, chaine de caractère). En le surchargeant on peut gérer la saisie
d'objet de n'importe quelle classe.
h Comme la surcharge de l'opérateur d'insertion sa syntaxe est assez
particulière par rapport aux autres opérateurs :
Exemple :
#include istream& operator >>(istream& is, CTab& tb)
8
using namespace std;
class CTab{private:
int T[TMAX];public:
CTab();friend istream& operator >>(istream& is, CTab& tb);
} ;
CTab::CTab(){
for(int i=0;itb.T[i];}
return is;
}
void main (void){
CTab t;cout
-
8/18/2019 Cours Math c++ fr
9/43
9
-
8/18/2019 Cours Math c++ fr
10/43
F
Les fonctions d'entrées/sorties sont implémentées dans une libraire standard
C++ appelée I/O stream [Input/Output stream ≡ flots d'entrées/sorties]. En
C++, les entrées/sorties sont des échanges de séquences de caractères ou
octets, appelées flots de données. Un flux est un périphérique, un fichier ou
une zone mémoire, qui reçoit (flux d'entrée) ou au contraire qui fournit (flux
de sortie) un flot de données.
Librairie I/O stream
10
La libraire I/O stream contient deux classes de base, ios et streambuf, et
plusieurs classes dérivées, (voir figure suivante).
i La classe streambuf et ses classes dérivées définissent des tampons pour les
flots. Les tampons sont des zones mémoires qui servent de relais entre lesvariables du programme et optimisent les échanges en réduisant le nombre
des appels systèmes qui sont souvent bien longs.
i La classe ios et ses classes dérivées définissent les opérations sur ces flots.
-
8/18/2019 Cours Math c++ fr
11/43
L I/
11
-
8/18/2019 Cours Math c++ fr
12/43
>
Entrées-Sorties standards
iPour lire ou écrire des données dans un flux, les deux opérateurs
d’insertion >> et d’extraction
-
8/18/2019 Cours Math c++ fr
13/43
E >
Exemple : CE
20; ;:
&( &, CE &);;
&( &, CE &)
>> . >> .; ;
()
CE 1; > 1;
-
8/18/2019 Cours Math c++ fr
14/43
F (1/2)
Etats de Formats
Pour formater les sorties par défaut, on utilise des manipulateurs simples ou
on appelle directement des fonctions membres de la classe de base ios. Les
manipulateurs simples s'emploient sous la forme :
flux > manipulateur
( )
14
Exemple :int i = 512; double d = 123.4;
cout
-
8/18/2019 Cours Math c++ fr
15/43
F (2/2)
Contrôle du format des entrées-sortiesPlusieurs fonctions membres de la classe ios modifient les données membres de
cette classe pour contrôler les formats d'entrée et/ou de sortie des flots. (voir
polycopié)
Exemple :double pi = 3.1415926535897932385;
cout
-
8/18/2019 Cours Math c++ fr
16/43
(1/2)
Manipulation de flux
Toutes les opérations d'entrée/sortie sur un flux sont réalisées dans un
tampon. C'est pourquoi les classes ios, istream, ostream et iostream reçoivent
un tampon comme unique paramètre pour leurs constructeurs.Afin de réduire cette contrainte, les trois classes ofstream, ifstream, et
fstream dérivées respectivement de ostream, istream et iostream, permettent
de manipuler très simplement des flux en créant automatiquement un tampon
16
associé au flux. On utilise principalement quatre fonctions membres de cesclasses.
(i) [i/o]fstream ( );
(ii) [i/o]fstream (int d);(iii) [i/o]fstream(const char*fname,int mode,int prot=filebuf::openprot);
(iv) [i/o]fstream (int d, char *p, int len);
-
8/18/2019 Cours Math c++ fr
17/43
(2/2)
Explication :
i La première version n'a pas de paramètre et construit un objet [i/o]fstream
qui n'est pas ouvert.
i La seconde version reçoit un unique paramètre et construit un objet[i/o]fstream relié à un descripteur de flux d.
i '
17
. ,
avec le mode d'ouverture spécifié par mode et le mode de protection spécifiépar prot. Le tableau suivant précise les différents modes d'ouverture
possibles, qui peuvent être combinés entre eux à l'aide de l'opérateur ou (|).
iLa quatrième version reçoit elle aussi trois paramètres. Le premier est unobjet associé à un descripteur de flux d. Ce constructeur permet de construire
un objet tampon streambuf, de taille len caractères et qui commence à
l'adresse p. Si p vaut NULL ou que len est égale à zéro, l'objet associé filebuf
n'est pas tamponné.
-
8/18/2019 Cours Math c++ fr
18/43
M
Mode d’ouverture Action
ios::in ouverture en lecture seule (obligatoire pour laclasse ifstream)
ios::out ouverture en écriture seule (obligatoire pour
ofstream)ios::binary ouverture en mode binaireios::app ouverture en ajout de données (écriture en fin
18
ios::ate déplacement en fin de flux après ouvertureios::trunc si le flux existe, son contenu est effacé
(obligatoire si ios::out est activé sans ios::ate niios::app)
ios::nocreate le flux doit exister préalablement à l'ouvertureios::noreplace le flux ne doit pas exister préalablement à
l'ouverture (sauf si ios::ate ou ios::app estactivé)
-
8/18/2019 Cours Math c++ fr
19/43
/F i
Ouverture de flux (open())La fonction [i/o]fstream::open (const char* fname, int mode, int
prot=filebuf::openprot) ; permet d'ouvrir un flux fname, avec le mode
d'ouverture spécifié par mode et le mode de protection spécifié par prot. Le
tableau précédent précise les différents modes d'ouverture possibles, quipeuvent être combinés entre eux à l'aide de l'opérateur ou (|).
i Fermeture de flux (close())
19
La fonction fstreambase::close ( ) ferme le tampon attaché à l'objet de laclasse [i/o]fstream en supprimant la connexion entre l'objet et le descripteur
de flux.
i Flux en écriture
La fonction ostream& ostream::put (char c) insère le caractère c dans le
tampon associé à l'objet de la classe [i/o]fstream. Pour insérer plusieurs
caractères simultanément, il faut utiliser la fonction
ostream& ostream::write (char* cp, int n) qui insère n caractères stockés à
l'adresse pointée par cp.
-
8/18/2019 Cours Math c++ fr
20/43
D
Pour déplacer le pointeur d'élément dans le flux, il faut utiliser la fonction
ostream& ostream::seekp (streamoff n, ios::seek_dir dir) qui positionne
le pointeur à n octets de la position dir. dir peut prendre l'une des valeurs du
tableau suivant.
Position dans le flux Action
ios::beg Début du flux
20
Pour connaître la valeur courante du pointeur d'élément, on utilise la fonction
streampos ostream::tellp ( ).
ios::cur position courante du flux
ios::end fin du flux
-
8/18/2019 Cours Math c++ fr
21/43
L
i Flux en lectureLa fonction istream& istream::get (char c) extrait un caractère du tamponassocié à l'objet de la classe [i/o]fstream et le place dans c. Pour extraireplusieurs caractères simultanément, il faut utiliser la fonctionistream& istream::read (char* cp, int n) qui extrait n caractères dutampon et les stocke à l'adresse pointée par cp.
Pour déplacer le pointeur d'élément dans le flux, il faut utiliser la fonction
21
, _
pointeur à n octets de la position dir (les différentes valeurs de dir sontregroupées dans le tableau précédent).
Pour connaître la valeur courante du pointeur d'élément, on utilise la fonction
streampos istream::tellg ( ).
-
8/18/2019 Cours Math c++ fr
22/43
Exemple : Ecriture dans un flux texte
# # # # # 16
()
; ; * = ".";
22
(=0;
-
8/18/2019 Cours Math c++ fr
23/43
Exemple : Lecture dans un flux texte
# # # # # 16
()
; ;
23
* = ".";
(, ::); (!)
-
8/18/2019 Cours Math c++ fr
24/43
Exemple : Ecriture dans un flux binaire
# # # # # 16
()
; ; * = "."
24
(=0;
-
8/18/2019 Cours Math c++ fr
25/43
Exemple : Lecture dans un flux binaire
# # # # # 16
()
; ;
25
* = ".";
(, ::); (!)
-
8/18/2019 Cours Math c++ fr
26/43
E (1/2)
Les états d'erreurs permettent de garder trace des erreurs qui peuvent
éventuellement survenir pendant la manipulation des flux, de la classe ios et
de toutes ses classes dérivées.
États d'erreur Signification
ios::goodbit aucun bit d'erreur n'est activé
26
ios::eofbit marque fin de flux rencontrée pendant uneextraction
ios::failbit erreur d'allocation mémoire pendantl'utilisation d'un flux
ios::badbit erreur fatale sur le tampon (streambuf) associéau flux
-
8/18/2019 Cours Math c++ fr
27/43
E (2/2)
Pour préserver l'encapsulation des données, on accède aux valeurs des
différents états d'erreurs au moyen de fonctions membres publiques dont la
liste est donnée dans le tableau suivant
Fonctions membres Rôle
int bad ( ) const retourne une valeur non nulle si ios::badbit est activé
' '
27
spécifier plus d'un état) ou tous les états si le paramètre estnul
int eof ( ) const retourne une valeur non nulle si ios::eofbit est activé
int fail ( ) const retourne une valeur non nulle si ios::badbit ou ios::failbit
sont activésint good ( ) const renvoie une valeur non nulle si aucun bit d'erreur est activé
streambuf* rdbuf ( ) retourne un pointeur sur l'objet streambuf associé au flux
-
8/18/2019 Cours Math c++ fr
28/43
Héritage
28
Polymorphisme
-
8/18/2019 Cours Math c++ fr
29/43
H (1/7)L'héritage (ou dérivation) est un mécanisme qui permet de construire des
classes à partir d'autres classes. La dérivation permet à une classe dérivée
d'hériter des propriétés, c'est à dire des données et fonctions membres, d'une
classe de base. La nouvelle classe, appelée classe dérivée, est une extension
d'une classe existante, appelée classe de base.
Syntaxe :class base{
...
29
};class derivee : base{
...};
Remarque :Quand une classe dérivée hérite d'une classe de base, les données et les fonctions
membres de cette classe de base sont incorporées aux données et fonctions
membres de la classe dérivée. Une classe dérivée peut redéfinir des données ou
des fonctions membres d'une classe de base. Pour lever toute ambiguïté,
l'opérateur de résolution de portée :: peut être utilisé.
-
8/18/2019 Cours Math c++ fr
30/43
H (2/7)
Exemple :class CPoint{
double x,y; // coordonnées (x,y) d'un pointpublic:...
}class CCercle : CPoint{
double r; // rayon d'un cercleublic:
30
...}Dans cet exemple, la classe CCercle a trois données membres : x, y et r.
Exemple : Affectationvoid main ( ){
CPoint p;CCercle c;p = c; // valide, toutes les données de p sont initialiséesc = p; // interdit, r n'est pas initialisé.
}
/
-
8/18/2019 Cours Math c++ fr
31/43
H (3/7)
Constructeur et destructeursQuand une classe dérivée possède plusieurs classes de base (hiérarchie), leconstructeur appelé en premier est celui de la classe la plus ancêtre, le dernierétant toujours celui de la classe dérivée. Cela permet d'initialiser en cascadetoutes les données membres des classes d'une hiérarchie.
Pour passer des paramètres au constructeur de la classe de base, il suffit depréciser la liste de ces paramètres à la suite de l'en-tête du constructeur de laclasse dérivée (en séparant cette liste de l'en-tête par le symbole :).
31
class CBase{...
public:CBase (paramètres CBase) {corps};
};class CDerive : CBase{
...public:CDerive (paramètres_CDerive) : CBase (paramètres_CBase) {corps};
};
( / )
-
8/18/2019 Cours Math c++ fr
32/43
H (4/7)
Exemple :#include
class CPoint
{
double x,y; // coordonnées d'un pointpublic:
CPoint (double a=0, double b=0) { x = a; y = b; }
}
32
class CCercle : CPoint
{
double ray; // rayon
public:
CCercle (double a, double b, double r=0) : CPoint (a,b) {ray = r;}
}
Remarque :
Dans une hiérarchie les destructeurs sont appelés dans l’ordre inverse des
constructeurs.
H ( / )
-
8/18/2019 Cours Math c++ fr
33/43
H (5/7)
Accès aux membres hérités
Les classes dérivées n'héritent pas automatiquement des privilèges des
classes de base. Ainsi, dans une classe dérivée, les spécificateurs private,
public et protected permettent de contrôler précisément l'accès aux membres
des classes de base.
Membres privés : Les membres privés (private) d'une classe sont
33
naccess es ou e au re c asse, y compr s une c asse r v e. ns , e
principe de l'abstraction des données est complètement préservé.
Membres protégés : Les membres d'une classe qui sont déclarés protégés
(protected) sont privés, sauf pour les classes dérivées dans lesquelles ils
peuvent être utilisés directement.
Membres publics : Les membres publics (public) d'une classe sont
accessibles partout.
H (6/7)
-
8/18/2019 Cours Math c++ fr
34/43
H (6/7)Syntaxe :
class CBase{….
}class CDerive1 : public CBase{….
}class CDerive2 : private CBase{….
}
34
Trois cas se présentent :
– Si une classe de base est déclarée publique, les membres publics et protégés dela classe de base restent membres publics et protégés de la classe dérivée,
– Si une classe de base est déclarée privée (accès par défaut), les membrespublics et protégés de la classe de base deviennent membres privés de la classedérivée,
– Si une classe de base est déclarée protégée, les membres publics et protégés dela classe de base deviennent membres protégés de la classe dérivée.
Dans tous les cas, les membres privés d'une classe de base restent privésdans les classes dérivées. C'est le concepteur d'une classe (et lui seul) qui
autorise ou non l'accès aux membres de sa classe.
H (7/7)
-
8/18/2019 Cours Math c++ fr
35/43
H (7/7)
Autre cas : restauration locale de l'accès à un membre d'une classe de base
class CBase
{
...public:
int i;
}
35
class CDerive1 : private CBase // les membres de base sont privés{
...
public:
CBase::i; // restauration de i publique dans la classe dérivée
}
H (1/4)
-
8/18/2019 Cours Math c++ fr
36/43
H (1/4)Héritage direct
Syntaxe :class A{….
};
class B{
….};
36
c ass
{….
};class X : public A, private B, public C{
….};
Remarque :L'ordre de déclaration des classes de base ne sert qu'à déterminer l'ordre d'appeldes constructeurs et des destructeurs de la hiérarchie.
H (2/4)
-
8/18/2019 Cours Math c++ fr
37/43
H (2/4)
C
La classe X hérite de la classe A par les classes B et C.
37
Remarque :
Un tel schéma conduit à des ambiguïtés puisque deux objets de classe A
accessibles dans X existent. Il est néanmoins possible de lever ces ambiguïtés
en utilisant l'opérateur de résolution de portée pour référencer explicitement
B::A ou C::A.
( / )
-
8/18/2019 Cours Math c++ fr
38/43
H (3/4)
Classes de base virtuelles
Lorsqu'au moins deux classes d'une hiérarchie ont une classe de base commune,
il est possible de déclarer cette classe commune virtuelle, de manière à forcer le
partage d'une unique instance plutôt que deux copies séparées. Ainsi, dans le
schéma suivant, les classes B et C ancêtres de X partagent la même classe A.
38
Pour obliger la classe X à n'hériter que d'un objet de classe A, il suffit de
préciser le mot réservé virtual devant A lors de la déclaration des classes B et C.
H (4/4)
-
8/18/2019 Cours Math c++ fr
39/43
H (4/4)Syntaxe :
class A
{
….
};
class B : virtual public A
{
….
};
39
{ ….
};
class X : public B, public C
{
….};
Remarque :Il est possible qu'une classe dérivée ait à la fois des classes de base virtuelles etnon virtuelles.
(1/4)
-
8/18/2019 Cours Math c++ fr
40/43
(1/4)En POO, l'édition de liens dynamiques est possible et permet d'écrire des
programmes très modulaires. En effet, grâce aux fonctions virtuelles, il est
possible de définir dans les classes d'une hiérarchie plusieurs
implémentations d'une même fonction membre, commune aux classes de
cette hiérarchie. C'est pendant l'exécution du programme que le système
sélectionne la fonction membre appelée, selon le type de l'objet courant. Ceprocessus qui permet de donner plusieurs implémentations à des fonctions
identiques dans toute une hiérarchie de classes s'appelle polymorphisme.
40
Fonctions virtuelles
On sait qu’un pointeur sur une classe dérivée est aussi un pointeur sur une
classe de base (la réciproque n'est pas vraie) et par défaut, le type des objets
pointés est défini lors de la compilation.
Exemple :class A class B : public A{ {... ...
public: public:void fct ( ); void fct ( );... ...
}; };
(2/4)
-
8/18/2019 Cours Math c++ fr
41/43
(2/4)
Exemple (suite) :main (void){A *pa;B *pb;
pa = pb;}
l'affectation pa = pb est autorisée, mais quel que soit le contenu de pa (pointeur
sur un objet de classe A ou B), pa->fct ( ) appelle toujours la fonction fct ( ) de
41
.
L'utilisation de fonctions virtuelles permet de contourner ce problème. lesappels aux fonctions sont résolus pendant l'exécution du programme, et non
plus à la compilation. Dans ce cas, on parle de ligature dynamique des
fonctions, puisque le choix de la fonction à appeler est réalisé lors de
l'exécution du programme et non plus lors de la compilation.
Syntaxe :
public:
virtual type fonction ( );
(3/4)
-
8/18/2019 Cours Math c++ fr
42/43
(3/4)
Remarques :
iPour qu'une fonction soit virtuelle dans toute une hiérarchie, il faut que
le nombre ou le type de ses arguments soit rigoureusement identique
dans toutes les classes dérivées.
iUne fonction déclarée virtuelle dans une classe de base peut ou non être
redéfinie dans des classes dérivées.
42
iLe mot réservé virtual ne s'emploie qu'une fois pour une fonction
donnée, impliquant que toute redéfinition de cette fonction dans des
classes dérivées est virtuelle.
iUn constructeur ne peut pas être virtuel mais un destructeur peut l'être.
iUne fonction virtuelle peut être déclarée amie dans une autre classe.
(4/4)
-
8/18/2019 Cours Math c++ fr
43/43
(4/4)Fonctions virtuelles pures :
Une classe abstraite est une classe de base qui regroupe des caractéristiquescommunes à toute une hiérarchie de classes. Dans la mesure où ses classesdérivées la complètent, cette classe de base ne doit généralement pas êtreinstanciée. En C++, pour interdire l'instanciation d'une classe, il suffit de donnerà cette classe une fonction membre virtuelle pure, publique, de la formesuivante :
Syntaxe :
public:
virtual type fonction ( ) = 0;
43
Remarques :
i Une fonction virtuelle pure n'a pas de définition et ne peut être appelée.
i Puisqu'une fonction virtuelle pure n'est pas définie, tout appel à une fonction
virtuelle pure est indéfini. Cependant, l'appel d'une fonction virtuelle pure ne
produit pas d'erreur.
i Aucun objet d'une classe ayant une fonction virtuelle pure ne peut être déclaré.
i Si une classe de base contient une fonction virtuelle pure et que sa classe
dérivée ne redéfinit pas cette fonction virtuelle pure, alors la classe dérivée est
elle aussi une classe abstraite qui ne peut être instanciée.