Cours Math c++ fr

Embed Size (px)

Citation preview

  • 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.