<ul><li>Programmation Orientée Objet </li></ul><ul><li>+ de cours sur  http:// coursuniversite.com /   </li></ul>
Plan du document <ul><li>De la programmation classique à la POO </li></ul><ul><li>Avantages de la POO </li></ul><ul><li>Ex...
Programmation << classique >> <ul><li>Objectif :  écrire une séquence d'instructions de telle façon qu'un ordinateur produ...
Décomposition fonctionnelle <ul><li>Le programme est une fonction principale </li></ul><ul><li>int main(argc, argv[]) </li...
Programmation orientée objets <ul><li>Tous les ingrédients de la programmation procédurale classique sont présents </li></...
Décomposition fonctionnelle classique main() init() calcule() trie() compare() permute() factorise() Données Données
Décomposition orientée objets init() calcule() trie() compare() permute() factorise() Données Données
Habituellement, un programme c'est une suite d'instructions. L'ordinateur est très bête et il faut tout lui détailler. Exe...
En programmation objet, on associe aux objets des actions (aussi appellées  méthodes ).  Par exemple, à l'objet  porte  on...
Bien sûr il faut détailler ce que fait la méthode  ouvrir  de  porte  et la méthode  allumer  de  lumière . On ne va pas d...
On peut changer la porte en mettant une porte automatique.  On peut aussi l'ouvrir (même si la porte elle-même ne s'ouvre ...
La programmation objet a plusieurs intérêts, entre autres: Vous pouvez utiliser des objets sans savoir comment ils sont pr...
Qu’est-ce qu’un objet ?   + de cours sur  http:// coursuniversite.com /
Objets de la vie courante grosminet titi felix garfield Rêve poursuit poursuit mange parle odie 0605040302 0102030405 0203...
Les objets coopèrent
Objet boîte noire <ul><li>Services rendus par l’objet : </li></ul><ul><ul><li>Démarrer ; </li></ul></ul><ul><ul><li>Arrête...
Objet logiciel <ul><li>Abstraction </li></ul><ul><ul><li>Représentation abstraite des entités du monde réel ou virtuel dan...
Téléphone portable État  appeler (personne) appeler (Bob) monTéléphone voirRépertoire() chercher Numero (personne) recevoi...
État d’un objet <ul><li>Attribut  </li></ul><ul><ul><li>Information qui qualifie l’objet qui le contient </li></ul></ul><u...
Comportement d’un objet <ul><li>Décrit les actions et les réactions d’un objet </li></ul><ul><ul><li>Compétences d’un obje...
Les objets communiquent <ul><li>Permet de reconstituer une fonction par une mise en collaboration d’un groupe d’objets : e...
Identité d’un objet <ul><li>Caractérise son existence propre </li></ul><ul><li>Indépendant du concept d’état </li></ul><ul...
Classe <ul><li>Description d’une famille d’objets </li></ul><ul><ul><li>Mêmes attributs </li></ul></ul><ul><ul><li>Même mé...
Classe CompteBancaire CompteBancaire CompteBancaire solde déposer() retirer() attributs opérations Nom de la classe
Instance <ul><li>Chaque objet appartient à une classe </li></ul><ul><li>Relation d’instanciation « instance de » </li></ul...
Constructeur <ul><li>Un objet doit être créé au sein d’une classe == moule </li></ul><ul><li>Méthode particulière : constr...
Héritage: les concepts   + de cours sur  http:// coursuniversite.com /
Généralisation et spécialisation <ul><li>Généralisation </li></ul><ul><ul><li>Factoriser les éléments communs (attributs, ...
Généralisation Constat: des caractéristiques communes calculerIntérêts () créditerIntérêts () changerTaux () déposer () re...
Généralisation Nota : La sémantique de  retirer   est différente  calculerIntérêts () créditerIntérêts () changerTaux () t...
Spécialisation Un PlanEpargneLogement  est un  CompteEpargne ayant des caractéristiques propres  calculerMontantPrêt() ret...
Arborescence d'héritage changerDecouvert () retirer () montantDécouvAutorisé CompteChèque calculerIntérêts () créditerInté...
Redéfinition d’une méthode  Sémantique de la méthode  retirer : CompteChèque : retrait autorisé suivant découvert CompteEp...
Redéfinition d’une méthode <ul><li>class CompteEpargne public CompteBancaire  </li></ul><ul><li>{ </li></ul><ul><ul><li>//...
Héritage et sous classes <ul><li>Héritage  </li></ul><ul><ul><li>Mécanisme permettant de dériver une classe à partir d'une...
Associer les classes : Les concepts   + de cours sur  http:// coursuniversite.com /
Association Une agence gère plusieurs clients. Un client possède un et un seul compte courant. gérer Compte Client Agence ...
Multiplicités les plus courantes 1 Un et un seul 0..1 Zéro ou un M..N De M à N (entiers naturels) * De zéro à plusieurs 0....
<ul><li>L’attribut compteCourant est une référence sur un objet de la classe CompteBancaire </li></ul>Association simple: ...
Association multiple : Tableau de références sur des objets unClient:Client uneAgence:Agence nom adresse lesClients * 500 ...
Une traduction d'associations gérer * 1 Compte lesDépôts  : entier[100] lesRetraits  : entier[100] déposer(...) retirer(.....
<ul><li>Programmation Objet en C++ </li></ul>
Le langage C++ se veut un langage C amélioré. Il possède des fonctionnalités supplémentaires, et notamment * la surcharge ...
Incompatibilités entre C et C++ <ul><li>Toute fonction doit </li></ul><ul><li>–  être définie avant utilisation </li></ul>...
Entrées-sorties <ul><li>Les entrées et sorties sont gérées dans C++ à  </li></ul><ul><li>travers des objets particuliers a...
E/S exemple 1 <ul><li>#include <iostream.h> </li></ul><ul><li>main() { </li></ul><ul><li>cout << &quot;Bonjour, monde !n&q...
Commentaires <ul><li>/* commentaire </li></ul><ul><li>// commentaire </li></ul><ul><li>commentaire </li></ul><ul><li>*/ </...
Emplacement des déclarations <ul><li>Une déclaration peut apparaître en n'importe  </li></ul><ul><li>quelle position d'un ...
Arguments par référence <ul><li>Enfin le passage par référence qui manque au C. </li></ul><ul><li>Un paramètre dont le nom...
Références Constantes <ul><li>Passage par référence constante pour </li></ul><ul><li>ne pas copier l'argument à l'appel; <...
Arguments par défaut <ul><li>Les derniers arguments d'une fonction/méthode peuvent  </li></ul><ul><li>prendre des ''valeur...
Surcharge <ul><li>Un même identificateur peut désigner plusieurs fonctions, si elles </li></ul><ul><li>diffèrent par la li...
Allocation dynamique <ul><li>Deux Opérateurs Intégrés au langage. </li></ul><ul><li>Les opérateurs new et delete gèrent la...
Fonctions/Méthodes « en ligne » <ul><li>Une fonction en ligne (inline) est une fonction dont  </li></ul><ul><li>les Instru...
Classes et objets <ul><li>Une classe est une structure, dont les attributs sont des  </li></ul><ul><li>données ou des méth...
<ul><li>La définition d'une méthode se fait soit en ligne,  </li></ul><ul><li>soit séparément; dans le deuxième cas, elle ...
<ul><li>La surcharge d'opérateurs permet de définir une forme  </li></ul><ul><li>agréable pour des opérations sur des obje...
<ul><li>Classes </li></ul><ul><li>1. Objectif </li></ul><ul><li>2. Déclaration </li></ul><ul><li>3. Définition </li></ul><...
Objectifs <ul><li>Une classe est la description d'une famille  </li></ul><ul><li>d'objets ayant même structure et même  </...
<ul><li>Avantages !!! </li></ul><ul><li>* simplifie l'utilisation des objets, </li></ul><ul><li>* rapproche les données et...
<ul><li>La déclaration d'une classe donne la nature des  </li></ul><ul><li>membres (type, signature), et les droits d'accè...
Déclaration <ul><li>La syntaxe est celle des structures. Une struct est une  </li></ul><ul><li>classe dont tous les attrib...
Définition <ul><li>L' opérateur de portée  ::  indique la classe à  </li></ul><ul><li>laquelle appartient la méthode. </li...
<ul><li>Les champs x, y invoqués dans les  </li></ul><ul><li>méthodes sont ceux de l'objet qui appelle la  </li></ul><ul><...
Utilisation <ul><li>void main() { </li></ul><ul><li>Point a, b; </li></ul><ul><li>a.setPoint(1, 2); </li></ul><ul><li>b.se...
Encapsulation <ul><li>Principe de programmation : </li></ul><ul><li>Il s'agit de  ne  montrer à l'utilisateur que ce qui l...
// Fichier main.c #include &quot;point.h&quot; void main() { Point a(1,2), b(3,-5); a.affiche(); b.affiche(); a.deplace(1,...
Constructeurs <ul><li>Les constructeurs permettent de définir les initialisations  </li></ul><ul><li>possible des instance...
<ul><li>Le constructeur par défaut est utilisé </li></ul><ul><li>* lors de la définition d'un objet, par </li></ul><ul><li...
Destructeur <ul><li>Le destructeur est noté ~X() pour une classe X. </li></ul><ul><li>Il est utilisé </li></ul><ul><li>* l...
Exemple constructeur <ul><li>Remplacement de la méthode setPoint par un constructeur : </li></ul><ul><li>class Point { </l...
<ul><li>Variations </li></ul><ul><li>* Un constructeur simple peut être défini en ligne,  </li></ul><ul><li>par </li></ul>...
Tableaux d'Objets <ul><li>Tableaux d'objets attention le constructeur par défaut est  </li></ul><ul><li>appelé sur chaque ...
Construction&Destruction <ul><li>La mention explicite du constructeur par défaut et du destructeur  </li></ul><ul><li>sign...
Une classe de Complexes <ul><li>class Complexe { </li></ul><ul><li>double re, im; </li></ul><ul><li>public: </li></ul><ul>...
<ul><li>En utilisant les arguments par défaut, les trois  </li></ul><ul><li>constructeurs se réduisent en un seul. </li></...
Une interface plus complète <ul><li>La déclaration est: </li></ul><ul><li>#include <iostream.h> </li></ul><ul><li>#include...
<ul><li>// Implémentation </li></ul><ul><li>Complexe::Complexe(double re, double im): re(re), im(im){} </li></ul><ul><li>d...
Les rationnels <ul><li>L'objectif est de montrer l'utilisation de surcharges,  </li></ul><ul><li>cette fois-ci sur les opé...
<ul><li>class Rat { </li></ul><ul><li>static int pgcd(int,int); </li></ul><ul><li>public: </li></ul><ul><li>int num, den; ...
Exemple de Surcharge d'opérateurs <ul><li>Comme toute fonction, un opérateur peut également être surchargé.  </li></ul><ul...
<ul><li>Nous définissons les quatre opérations arithmétiques par: </li></ul><ul><li>Rat operator+(Rat a, Rat b) { </li></u...
<ul><li>Les rationnels passé en argument ne sont pas modifiés, on peut donc  </li></ul><ul><li>les spécifier const Rat&. <...
Donnée membre  statique <ul><li>Une donnée membre  statique  est spécifiée  </li></ul><ul><li>par static. </li></ul><ul><l...
Exemple de donnée statique <ul><li>#include <iostream.h> </li></ul><ul><li>class XY { </li></ul><ul><li>public: </li></ul>...
Copie et affectation <ul><li>1. Constructeurs </li></ul><ul><li>2. Constructeur de copie </li></ul><ul><li>3. Affectation ...
Constructeurs <ul><li>Les constructeurs se classent syntaxiquement  </li></ul><ul><li>en 4 catégories </li></ul><ul><li>1....
constructeur de conversion <ul><li>Un constructeur de conversion sert souvent à la promotion. </li></ul><ul><li>Exemple: <...
Constructeur de copie <ul><li>Chaque classe possède un constructeur de copie  </li></ul><ul><li>(ne pas confondre avec l'o...
<ul><li>Le constructeur de copie est utilisé </li></ul><ul><li>* lors d'une initialisation: </li></ul><ul><li>X x = y; </l...
<ul><li>Voici une classe Pt possédant: </li></ul><ul><li>* Un constructeur de copie Pt(const Pt& p) </li></ul><ul><li>* Un...
Affectation <ul><li>L'affectation et la copie sont des opérations différentes. </li></ul><ul><li>* le constructeur de copi...
<ul><li>La signature de l'opérateur est </li></ul><ul><li>X& operator=(X&) </li></ul><ul><li>X& operator=(const X&) </li><...
Fonctions amies <ul><li>L'amitié permet d'accéder aux parties privées. </li></ul><ul><li>Une ''déclaration d'amitié'' inco...
<ul><li>Fonction membre de Y </li></ul><ul><li>class Y { ... </li></ul><ul><li>void f(X& x); </li></ul><ul><li>} </li></ul...
Opérateurs amis <ul><li>Une fonction amie d'une classe a les mêmes droits qu'une  </li></ul><ul><li>fonction membre, et en...
<ul><li>L'addition </li></ul><ul><li>Rat operator+(const Rat& a, const Rat& b) { </li></ul><ul><li>int n = a.getNum()*b.ge...
Syntaxe <ul><li>Un opérateur est unaire, binaire. </li></ul><ul><li>Un opérateur peut être défini </li></ul><ul><li>* soit...
<ul><li>* opérateur unaire au niveau global: </li></ul><ul><li>type operatorop(type); </li></ul><ul><li>Rat operator-(Rat)...
Un Conseil <ul><li>* Choisir un opérateur global et ami lorsque l'opération est symétrique: + - * / == </li></ul><ul><li>*...
<ul><li>Avec </li></ul><ul><li>Rat Rat::operator-(Rat b) {return Rat(num*b.den - den* b.num, den*b.den);} </li></ul><ul><l...
Héritage <ul><li>1. Objectif </li></ul><ul><li>2. Classe composée ou classe dérivée </li></ul><ul><li>3. Syntaxe </li></ul...
Objectif <ul><li>L'héritage est l'un des principes fondamentaux de la  </li></ul><ul><li>programmation objet. Il a pour ob...
Avantages: <ul><li>* Une classe dérivée modélise un cas particulier  </li></ul><ul><li>de la classe de base, et peut donc ...
Composition ou Héritage <ul><li>Une classe est composée si certains de ses membres sont eux-mêmes des objets. </li></ul><u...
Syntaxe <ul><li>La syntaxe pour la définition d'une classe dérivée est </li></ul><ul><li>class classe_derivee : protection...
Des Exemples <ul><li>* Une voiture comporte quatre (ou cinq) roues, donc </li></ul><ul><li>class Automobile { </li></ul><u...
Accès aux données et méthodes <ul><li>Les attributs de la classe de base peuvent être désignés directement  </li></ul><ul>...
Implantations <ul><li>DescrHabitant::DescrHabitant() { </li></ul><ul><li>cout << &quot;Entrez votre nom : &quot;; cin >> n...
Héritage multiple <ul><li>Une classe peut hériter de plusieurs  </li></ul><ul><li>classes. Les classes de bases sont alors...
Prochain SlideShare
Chargement dans…5
×

programmation orienté objet c++

6 463 vues

Publié le

par : http://coursuniversite.com/
programmation orienté objet c++

Publié dans : Formation, Business
1 commentaire
17 j’aime
Statistiques
Remarques
Aucun téléchargement
Vues
Nombre de vues
6 463
Sur SlideShare
0
Issues des intégrations
0
Intégrations
5
Actions
Partages
0
Téléchargements
0
Commentaires
1
J’aime
17
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive
  • On perçoit le monde comme un ensemble d ’objets Un objet possède un nom, unique : identité. Deux jumeaux (Dupont et Dupond) sont 2 personnes distinctes. Identité = les objets peuvent être distingués grâce à leur existence inhérente et non grâce à la description des propriétés qu&apos;ils peuvent avoir. =&gt; Faire pressentir que l ’on abstrait la réalité: On classe les objets par famille en faisant abstraction de quelques différences, de détails non pertinents. On élabore une définition théorique de ce que doit être un objet de cette classe Quand on voit un téléphone, quelle que soit la marque ou le type, on sait qu’on va pouvoir composer un numéro. Faire pressentir la différence entre objet de la vie courante et objet logiciel (on en parle vraiment slide 5) - les objets peuvent interagir entre eux, cf. slide suivant
  • Objet coopératif Un objet agit sur son environnement On peut interagir avec la plupart des objets télé, téléphone, voiture Contre exemple : livre Chaque objet est capable de rendre un ensemble de services bien définis. On peut faire interagir les objets pour accomplir une tache complexe.
  • On n’a pas à savoir qu’il y a des bougies de préchauffage ou non (diesel ou non), un carburateur et encore moins la coopération (interne) des ces objets … pour démarrer sa voiture. Idem pour un téléviseur. La télécommande sert à adresser des signaux de changements d’états mais à aucun moment le téléspectateur n’a à ouvrir sa télé pour changer de chaîne.
  • Exercice conception Unité 1 sur le site web (&amp;quot;Définir les objets d&apos;un système&amp;quot;) Pour une voiture: services : démarrer État : niveaux (batterie, réservoirs) Identité : plaque d&apos;immatriculation La réalisation du service dépend de l&apos;état de l&apos;objet. La voiture démarre si niveau batterie OK
  • Illustre le transparent précédent. + Les services sont définis précisément. Si on demande un service non défini,il ne peut être réalisé.
  • Représentation graphique : rectangle avec une première partie pour l’identité d’objet, une deuxième pour attributs (constant ou variable) Conventions d’écritures - l’identité d’un attribut commence par une minuscule - quand on change de mot, majuscule - idem pour attribut variable - constante = tout en majuscule
  • Pour réaliser un service demandé,un objet peut demander la coopération d&apos;un autre objet en lui envoyant à son tour un message. et ainsi de suite.
  • Vous pouvez reprendre l&apos;exemple des Dupond et Dupont Exercice Conception sur le web : &amp;quot;Identité d&apos;objet&amp;quot;
  • Nom du constructeur = nom de la classe
  • programmation orienté objet c++

    1. 1. <ul><li>Programmation Orientée Objet </li></ul><ul><li>+ de cours sur http:// coursuniversite.com / </li></ul>
    2. 2. Plan du document <ul><li>De la programmation classique à la POO </li></ul><ul><li>Avantages de la POO </li></ul><ul><li>Exemples d’objets </li></ul><ul><li>Objet logiciel </li></ul><ul><ul><li>État </li></ul></ul><ul><ul><li>Comportement </li></ul></ul><ul><ul><li>Identité </li></ul></ul><ul><li>Concept de classe </li></ul><ul><ul><li>Catégorie </li></ul></ul><ul><ul><li>Classe </li></ul></ul><ul><ul><li>Instance </li></ul></ul><ul><ul><li>Constructeur </li></ul></ul><ul><li>Héritage </li></ul><ul><li>Association </li></ul>
    3. 3. Programmation << classique >> <ul><li>Objectif : écrire une séquence d'instructions de telle façon qu'un ordinateur produise une sortie appropriée pour une certaine entrée </li></ul><ul><li>Ingrédients : </li></ul><ul><ul><ul><li>décomposition fonctionnelle </li></ul></ul></ul><ul><ul><ul><li>variables </li></ul></ul></ul><ul><ul><ul><li>passages de paramètres </li></ul></ul></ul><ul><ul><ul><li>tests </li></ul></ul></ul><ul><ul><ul><li>boucles </li></ul></ul></ul><ul><ul><ul><li>structures </li></ul></ul></ul>
    4. 4. Décomposition fonctionnelle <ul><li>Le programme est une fonction principale </li></ul><ul><li>int main(argc, argv[]) </li></ul><ul><li>Cette fonction appelle des sous-fonctions </li></ul><ul><li>Qui en appellent d'autres… </li></ul>main() init() calcule() trie() affiche() compare() permute() factorise()
    5. 5. Programmation orientée objets <ul><li>Tous les ingrédients de la programmation procédurale classique sont présents </li></ul><ul><li>Mais la décomposition fonctionnelle n'est pas assez structurante pour des programmes très complexes </li></ul><ul><li>Structurer le programme autour des objets manipulés </li></ul><ul><li>Les traitements sont associés aux objets </li></ul><ul><li>Séparation plus claire entre données et traitements </li></ul>
    6. 6. Décomposition fonctionnelle classique main() init() calcule() trie() compare() permute() factorise() Données Données
    7. 7. Décomposition orientée objets init() calcule() trie() compare() permute() factorise() Données Données
    8. 8. Habituellement, un programme c'est une suite d'instructions. L'ordinateur est très bête et il faut tout lui détailler. Exemple programme d’ouverture de porte Tout se passe très bien. Mais qu'est-ce qui se passe par exemple si on met une porte automatique ? Le programme sera incapable de trouver la poignée et d'ouvrir la porte ! Avantages de la programmation objet Mettre la main sur la poignée de la porte Tourner la poignée Pousser la porte Mettre le doigt sur l'interrupteur Appuyer sur l'interrupteur pour allumer l'ampoule
    9. 9. En programmation objet, on associe aux objets des actions (aussi appellées méthodes ). Par exemple, à l'objet porte on peut associer la méthode ouvrir . De même pour l'ampoule on pourrait associer une méthode allumer , éteindre , etc. Le programme devient plus simple: On a plus besoin de savoir comment la portes'ouvre. On se contente de l'ouvrir. Pour indiquer qu'on applique la méthode (ouvrir) sur l'objet (porte), on note souvent objet . méthode (ici : porte.ouvrir). porte.ouvrir ampoule.allumer
    10. 10. Bien sûr il faut détailler ce que fait la méthode ouvrir de porte et la méthode allumer de lumière . On ne va pas détailler dans le programme ce que fait la méthode ouvrir, mais on va le détailler dans l'objet lui-même . C'est normal, puisque la méthode ouvrir ne s'applique qu'à la porte, pas à la lumière: porte.ouvrir : Mettre la main sur la poignée Tourner la poignée Pousser la porte
    11. 11. On peut changer la porte en mettant une porte automatique. On peut aussi l'ouvrir (même si la porte elle-même ne s'ouvre pas de la même façon): Mais votre programme pourra l'ouvrir sans rien changer: Le programme principal : il est inchangé malgré le changement de porte porte.ouvrir : Se placer devant la porte Attendre que la porte soit complètement ouverte porte.ouvrir ampoule.allumer
    12. 12. La programmation objet a plusieurs intérêts, entre autres: Vous pouvez utiliser des objets sans savoir comment ils sont programmés derrière (c'est le cas notre ouverture de porte). Les objets peuvent être modifiés sans avoir à modifier votre programme (c'est aussi le cas ici). Les objets sont facilement réutilisables dans de nouveaux programmes. Les langages objets offrent des mécanismes pour permettre ce genre de programmation.
    13. 13. Qu’est-ce qu’un objet ? + de cours sur http:// coursuniversite.com /
    14. 14. Objets de la vie courante grosminet titi felix garfield Rêve poursuit poursuit mange parle odie 0605040302 0102030405 0203040506 007BEJ06 45BEJ91 123CDE91 001-DF-YTR java 2 Dupond Dupont
    15. 15. Les objets coopèrent
    16. 16. Objet boîte noire <ul><li>Services rendus par l’objet : </li></ul><ul><ul><li>Démarrer ; </li></ul></ul><ul><ul><li>Arrêter ; </li></ul></ul><ul><ul><li>Accélérer ; </li></ul></ul><ul><ul><li>Freiner ; </li></ul></ul><ul><ul><li>Climatiser … </li></ul></ul><ul><li>Fonctionnement interne ??? </li></ul>
    17. 17. Objet logiciel <ul><li>Abstraction </li></ul><ul><ul><li>Représentation abstraite des entités du monde réel ou virtuel dans le but de les piloter ou de les simuler </li></ul></ul><ul><li>Programme, logiciel </li></ul>Objet = État + Comportement + Identité État Service Message = demande de service unObjet
    18. 18. Téléphone portable État appeler (personne) appeler (Bob) monTéléphone voirRépertoire() chercher Numero (personne) recevoir msg (msg) appeler (Bob et Paulette)
    19. 19. État d’un objet <ul><li>Attribut </li></ul><ul><ul><li>Information qui qualifie l’objet qui le contient </li></ul></ul><ul><ul><li>Peut être une constante </li></ul></ul><ul><li>État </li></ul><ul><ul><li>Valeurs instantanées de tous les attributs d’un objet </li></ul></ul><ul><ul><li>Évolue au cours du temps </li></ul></ul><ul><ul><li>Dépend de l’histoire de l’objet </li></ul></ul>solde DEBITAUTORISE compte001 : CompteBancaire Identité d’objet attribut variable attribut constant
    20. 20. Comportement d’un objet <ul><li>Décrit les actions et les réactions d’un objet </li></ul><ul><ul><li>Compétences d’un objet </li></ul></ul><ul><li>Service = opération = méthode </li></ul><ul><ul><li>Comportement déclenché par un message </li></ul></ul>compte001: CompteBancaire dupont : Client consulter () consulter() est un service offert par compte001
    21. 21. Les objets communiquent <ul><li>Permet de reconstituer une fonction par une mise en collaboration d’un groupe d’objets : envois de messages successifs </li></ul>c1 : CompteBancaire c2 : CompteBancaire créditX : Banque virer(m, c1, c2) retirer (m) déposer (m) dupont : Client
    22. 22. Identité d’un objet <ul><li>Caractérise son existence propre </li></ul><ul><li>Indépendant du concept d’état </li></ul><ul><li>Permet de désigner tout objet de façon non ambiguë </li></ul>compte001 :CompteBancaire 1000 1000 compte112 :CompteBancaire
    23. 23. Classe <ul><li>Description d’une famille d’objets </li></ul><ul><ul><li>Mêmes attributs </li></ul></ul><ul><ul><li>Même méthodes </li></ul></ul><ul><li>Réalisation (implantation) </li></ul><ul><ul><li>Décrit comment la spécification est réalisée </li></ul></ul><ul><li>Générateur d'objets = moule </li></ul>Spécification
    24. 24. Classe CompteBancaire CompteBancaire CompteBancaire solde déposer() retirer() attributs opérations Nom de la classe
    25. 25. Instance <ul><li>Chaque objet appartient à une classe </li></ul><ul><li>Relation d’instanciation « instance de » </li></ul>CompteBancaire compte001 : CompteBancaire Instance Classe Relation d’instanciation solde : 1000 <<instanciation>>
    26. 26. Constructeur <ul><li>Un objet doit être créé au sein d’une classe == moule </li></ul><ul><li>Méthode particulière : constructeur </li></ul><ul><ul><li>Construit l’objet avec ses attributs, ses méthodes </li></ul></ul><ul><ul><li>Initialise les valeurs des attributs </li></ul></ul><ul><ul><li>Nom du constructeur = Nom de la classe </li></ul></ul>CompteBancaire solde CompteBancaire() déposer() retirer() attributs opérations Nom de la classe Constructeur
    27. 27. Héritage: les concepts + de cours sur http:// coursuniversite.com /
    28. 28. Généralisation et spécialisation <ul><li>Généralisation </li></ul><ul><ul><li>Factoriser les éléments communs (attributs, opérations...) d’un ensemble de classes </li></ul></ul><ul><ul><ul><li>Simplifier les diagrammes (regroupements sémantiques) </li></ul></ul></ul><ul><ul><li>« est un », « est une sorte de » </li></ul></ul><ul><li>Spécialisation </li></ul><ul><ul><li>Utiliser les caractéristiques d'une classe déjà identifiée et en spécifier de nouvelles. </li></ul></ul><ul><li>Hiérarchie de classe </li></ul><ul><ul><li>Arborescence des héritages </li></ul></ul>ClasseMère ClasseFille Spécialisation Généralisation
    29. 29. Généralisation Constat: des caractéristiques communes calculerIntérêts () créditerIntérêts () changerTaux () déposer () retirer () taux intérêts solde CompteEpargne changerDecouvert () déposer () retirer () montantDécouvAutorisé solde CompteChèque
    30. 30. Généralisation Nota : La sémantique de retirer est différente calculerIntérêts () créditerIntérêts () changerTaux () taux intérêts CompteEpargne changerDecouvert () retirer () montantDécouvertAutorisé CompteCheque déposer () retirer() solde CompteBancaire
    31. 31. Spécialisation Un PlanEpargneLogement est un CompteEpargne ayant des caractéristiques propres calculerMontantPrêt() retirer() durée dateDebut périodiciteVersement montantVersement PlanEpargneLogement calculerIntérêts () créditerIntérêts () changerTaux () taux intérêts CompteEpargne PlanEpargneLogement
    32. 32. Arborescence d'héritage changerDecouvert () retirer () montantDécouvAutorisé CompteChèque calculerIntérêts () créditerIntérêts () changerTaux () taux intérêts CompteEpargne déposer () retirer() solde CompteBancaire calculerMontantPrêt() retirer() durée dateDebut périodiciteVersement montantVersement PlanEpargneLogement
    33. 33. Redéfinition d’une méthode Sémantique de la méthode retirer : CompteChèque : retrait autorisé suivant découvert CompteEpargne : pas de découvert autorisé PlanEpargneLogement : pas de retrait calculerIntérêts () créditerIntérêts () changerTaux () taux intérêts CompteEpargne calculerMontantPrêt() retirer () durée dateDebut périodiciteVersement montantVersement PlanEpargneLogement déposer () retirer () solde CompteBancaire ChangDecouvert () retirer () montantDécouvertAutorisé CompteChèque
    34. 34. Redéfinition d’une méthode <ul><li>class CompteEpargne public CompteBancaire </li></ul><ul><li>{ </li></ul><ul><ul><li>// Pas de redéfinition de retirer() </li></ul></ul><ul><ul><li>// car héritage de CompteBancaire </li></ul></ul><ul><li>} </li></ul><ul><li>class CompteChèque public CompteBancaire </li></ul><ul><li>{ // Redéfinition de retirer() </li></ul><ul><li>void retirer ( double montant ) </li></ul><ul><li>{ </li></ul><ul><li>if (solde +decouvert >= montant) </li></ul><ul><ul><li>solde = solde - montant; </li></ul></ul><ul><li>} </li></ul><ul><li>//... </li></ul><ul><li>} </li></ul><ul><li>class CompteBancaire </li></ul><ul><li>{ // … </li></ul><ul><li>void retirer ( double montant ) </li></ul><ul><li>{ </li></ul><ul><li>if (solde >= montant) </li></ul><ul><ul><li>solde = solde - montant; </li></ul></ul><ul><li>} </li></ul><ul><li>//... </li></ul><ul><li>} </li></ul><ul><li>class PlanEpargneLogement public CompteBancaire </li></ul><ul><li>{ </li></ul><ul><ul><li>void retirer ( double montant ) </li></ul></ul><ul><ul><li>{ </li></ul></ul><ul><ul><li>cout << &quot;  Interdit  !! &quot; ; </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>} </li></ul>
    35. 35. Héritage et sous classes <ul><li>Héritage </li></ul><ul><ul><li>Mécanisme permettant de dériver une classe à partir d'une classe existante </li></ul></ul><ul><ul><li>Permet de classer </li></ul></ul><ul><ul><ul><li>Etendre structurellement et comportementalement une classe </li></ul></ul></ul><ul><ul><li>Permet de construire </li></ul></ul><ul><ul><ul><li>Réutiliser le code d'une classe existante </li></ul></ul></ul><ul><li>Classe dérivée </li></ul><ul><ul><li>Hérite de toutes les caractéristiques de son (ses) ancêtre(s) </li></ul></ul><ul><ul><li>Peut avoir des caractéristiques propres </li></ul></ul><ul><ul><li>Peut redéfinir des caractéristiques héritées </li></ul></ul>
    36. 36. Associer les classes : Les concepts + de cours sur http:// coursuniversite.com /
    37. 37. Association Une agence gère plusieurs clients. Un client possède un et un seul compte courant. gérer Compte Client Agence posséder
    38. 38. Multiplicités les plus courantes 1 Un et un seul 0..1 Zéro ou un M..N De M à N (entiers naturels) * De zéro à plusieurs 0..* De zéro à plusieurs 1..* D'un à plusieurs gérer * 1 Compte Client Agence posséder 1 1
    39. 39. <ul><li>L’attribut compteCourant est une référence sur un objet de la classe CompteBancaire </li></ul>Association simple: une référence comme attribut Client identifiant : entier annéeOuvertureCompte : entier compteCourant : CompteBancaire CompteBancaire
    40. 40. Association multiple : Tableau de références sur des objets unClient:Client uneAgence:Agence nom adresse lesClients * 500 BNP EVRY … 0 500 indice
    41. 41. Une traduction d'associations gérer * 1 Compte lesDépôts : entier[100] lesRetraits : entier[100] déposer(...) retirer(...) Client nom : chaîne âge : entier vieillir() changerNom(...) Agence directeur : chaîne adresse : chaîne changerDirecteur(...) ajouterUnClient(...) posséder 1 1 <ul><li>Une agence gère une liste de clients. </li></ul><ul><li>La référence de son compte fait partie des attributs d’un client. </li></ul>Client nom : chaîne âge : entier compte : Compte vieillir() changerNom(...) Agence directeur : chaîne adresse : chaîne lesClients : Clients[500] changerDirecteur(...) ajouterUnClient(...)
    42. 42. <ul><li>Programmation Objet en C++ </li></ul>
    43. 43. Le langage C++ se veut un langage C amélioré. Il possède des fonctionnalités supplémentaires, et notamment * la surcharge de fonctions * le passage par référence * l'emplacement des déclarations * l'allocation dynamique Les apports spécifiques de C++ sont * l'aide à l'abstraction de données: définition de types de données, et de leur implémentation concrète. * l'aide à la programmation objet: hiérarchie de classes et héritage. Meilleur C
    44. 44. Incompatibilités entre C et C++ <ul><li>Toute fonction doit </li></ul><ul><li>– être définie avant utilisation </li></ul><ul><li>– ou être déclarée par un prototype </li></ul><ul><li>float fct (int, double, char*); </li></ul><ul><li>(En C, une fonction non déclarée est supposée de type de </li></ul><ul><li>retour int.) </li></ul><ul><li>Une fonction qui ne retourne pas de valeur a le type de </li></ul><ul><li>retour void. </li></ul><ul><li>Le qualificatif const peut être utilisé pour une expression </li></ul><ul><li>Constante nécessaire pour la taille d'un tableau </li></ul><ul><li>const int N = 10; // remplace #define N 10 </li></ul><ul><li>int valeurs[N]; </li></ul>
    45. 45. Entrées-sorties <ul><li>Les entrées et sorties sont gérées dans C++ à </li></ul><ul><li>travers des objets particuliers appelées streams ou </li></ul><ul><li>flots. Inclure <iostream.h> </li></ul><ul><li>Deux opérateurs sont surchargés de manière </li></ul><ul><li>appropriée pour les flots: </li></ul><ul><li>* l'opérateur d' insertion << (écriture) </li></ul><ul><li>* l'opérateur d' extraction >> (lecture) </li></ul><ul><li>Trois flots prédéfinis sont </li></ul><ul><li>* cout attaché à la sortie standard; </li></ul><ul><li>* cerr attaché à la sortie erreur standard; </li></ul><ul><li>* cin attaché à l'entrée standard; </li></ul>
    46. 46. E/S exemple 1 <ul><li>#include <iostream.h> </li></ul><ul><li>main() { </li></ul><ul><li>cout << &quot;Bonjour, monde !n&quot;; </li></ul><ul><li>} </li></ul><ul><li>Plusieurs expressions: </li></ul><ul><li>cout << ex_1 << ex_2 << ... << ex_n ; </li></ul><ul><li>Plusieurs ''lvalues'': </li></ul><ul><li>cin >> lv_1 >> lv_2 >> ... >> lv_n ; </li></ul><ul><li>Les types écrits ou lus sont </li></ul><ul><li>char, short, int, long, float, double, char* </li></ul><ul><li>Exemple </li></ul><ul><li>#include <iostream.h> </li></ul><ul><li>int i; </li></ul><ul><li>main() { </li></ul><ul><li>cout << &quot;Un entier : &quot;; </li></ul><ul><li>cin >> i; </li></ul><ul><li>cout << &quot;Le carre de &quot; << i <<&quot; est &quot; << i*i << endl; </li></ul><ul><li>} </li></ul>
    47. 47. Commentaires <ul><li>/* commentaire </li></ul><ul><li>// commentaire </li></ul><ul><li>commentaire </li></ul><ul><li>*/ </li></ul><ul><li>// commentaire </li></ul>
    48. 48. Emplacement des déclarations <ul><li>Une déclaration peut apparaître en n'importe </li></ul><ul><li>quelle position d'un corps de classe ou de </li></ul><ul><li>fonction, mais doit précéder son utilisation. </li></ul><ul><li>int n; </li></ul><ul><li>n = 3; </li></ul><ul><li>int q = 2*n-1; </li></ul><ul><li>for (int i = 0; i<n ; i++) {...} // déconseillé </li></ul>
    49. 49. Arguments par référence <ul><li>Enfin le passage par référence qui manque au C. </li></ul><ul><li>Un paramètre dont le nom est suivi de & est transmis par </li></ul><ul><li>référence, donc pas de copie de l'argument à l'appel; </li></ul><ul><li>possibilité de modifier l'argument. </li></ul><ul><li>Déclaration </li></ul><ul><li>void echange(float&, float&) ; </li></ul><ul><li>Définition </li></ul><ul><li>void echange(float& a, float& b) { </li></ul><ul><li>float t = a; a = b; b = t; </li></ul><ul><li>} </li></ul><ul><li>Exemple </li></ul><ul><li>float x = 2, y = 3; </li></ul><ul><li>echange (x, y); </li></ul><ul><li>cout << x <<&quot;,&quot;<< y; //Affiche 3,2 </li></ul>
    50. 50. Références Constantes <ul><li>Passage par référence constante pour </li></ul><ul><li>ne pas copier l'argument à l'appel; </li></ul><ul><li>ne pas modifier l'argument : </li></ul><ul><li>void afficher(const objet&); </li></ul><ul><li>Passage par référence constante permet </li></ul><ul><li>d'assurer l'encapsulation en évitant la copie </li></ul><ul><li>sur la pile de structures trop grande. </li></ul>
    51. 51. Arguments par défaut <ul><li>Les derniers arguments d'une fonction/méthode peuvent </li></ul><ul><li>prendre des ''valeurs par défaut''. </li></ul><ul><li>Déclaration </li></ul><ul><li>float f(char, int = 10, char* = &quot;Tout&quot;); </li></ul><ul><li>Appels </li></ul><ul><li>f(c, n, &quot;rien&quot;) </li></ul><ul><li>f(c, n) // <-> f(c, n, &quot;Tout&quot;) </li></ul><ul><li>f(c) // <-> f(c,10, &quot;Tout&quot;) </li></ul><ul><li>f() // erreur </li></ul><ul><li>Seuls les derniers arguments peuvent avoir des valeurs par </li></ul><ul><li>défaut. </li></ul><ul><li>float f(char = 'a', int, char* = &quot;Tout&quot;); // erreur </li></ul>
    52. 52. Surcharge <ul><li>Un même identificateur peut désigner plusieurs fonctions, si elles </li></ul><ul><li>diffèrent par la liste des types de leurs arguments. </li></ul><ul><li>float max(float a, float b) { return (a > b) ? a : b;} </li></ul><ul><li>float max(float a, float b, float c) { return max(a, max(b, c));} </li></ul><ul><li>float max(int n, float t[]) { </li></ul><ul><li>if (!n) return 0; </li></ul><ul><li>float m = t[0]; for (int i = 1 ; i < n; i++) </li></ul><ul><li>m = max(m, t[i]); </li></ul><ul><li>return m; </li></ul><ul><li>} </li></ul><ul><li>void main() { </li></ul><ul><li>float x, y, z; </li></ul><ul><li>float T[] ={11.1, 22.2, 33.3, 44.4, 7.7, 8.8 }; </li></ul><ul><li>x = max (1.86, 3.14); </li></ul><ul><li>y = max (1.86, 3.14, 37.2); </li></ul><ul><li>z = max (6, T); </li></ul><ul><li>cout << x <<&quot; &quot;<< y <<&quot; &quot;<< z; </li></ul><ul><li>} </li></ul>
    53. 53. Allocation dynamique <ul><li>Deux Opérateurs Intégrés au langage. </li></ul><ul><li>Les opérateurs new et delete gèrent la mémoire </li></ul><ul><li>dynamiquement. </li></ul><ul><li>new chose[n] </li></ul><ul><li>alloue la place pour éléments de type chose et </li></ul><ul><li>retourne l'adresse du premier élément; </li></ul><ul><li>delete addresse </li></ul><ul><li>libère la place allouée par new. </li></ul><ul><li>int* a = new int; // malloc(sizeof(int)) </li></ul><ul><li>double* d = new double[100]; </li></ul><ul><li>// malloc(100*sizeof(double)) </li></ul>
    54. 54. Fonctions/Méthodes « en ligne » <ul><li>Une fonction en ligne (inline) est une fonction dont </li></ul><ul><li>les Instructions sont incorporées par le compilateur </li></ul><ul><li>dans le module objet à chaque appel. Donc il n'y </li></ul><ul><li>pas d'appel : gestion de contexte, gestion de pile; </li></ul><ul><li>Déclaration par qualificatif inline. </li></ul><ul><li>inline int sqr(int x) { return x*x; } </li></ul><ul><li>[ les méthodes définie dans le corps de classe </li></ul><ul><li>sont inlinées] </li></ul><ul><li>[ les fonctions trop grandes ou récursives ne sont </li></ul><ul><li>pas inlinées] </li></ul>
    55. 55. Classes et objets <ul><li>Une classe est une structure, dont les attributs sont des </li></ul><ul><li>données ou des méthodes. Un objet, ou une instance, est </li></ul><ul><li>un exemplaire de cette structure. </li></ul><ul><li>class Complexe { </li></ul><ul><li>public: </li></ul><ul><li>float re, im;//données </li></ul><ul><li>void show(); //méthode </li></ul><ul><li>}; </li></ul><ul><li>On déclare des objets de la classe par: </li></ul><ul><li>Complexe a, b; </li></ul><ul><li>On les manipule de manière usuelle: </li></ul><ul><li>a.re = b.im; b.re = 7; a.show(); </li></ul>
    56. 56. <ul><li>La définition d'une méthode se fait soit en ligne, </li></ul><ul><li>soit séparément; dans le deuxième cas, elle utilise </li></ul><ul><li>l' opérateur de portée noté :: pour désigner la classe. </li></ul><ul><li>void Complexe::show() { </li></ul><ul><li>cout << re << ' ' << im; </li></ul><ul><li>} </li></ul><ul><li>A l'appel a.show(), la méthode est celle de la classe </li></ul><ul><li>de a, donc Complexe::show(), et les champs re et im </li></ul><ul><li>sont ceux de l'objet appelant, c'est-à-dire a.re et a.im. </li></ul>
    57. 57. <ul><li>La surcharge d'opérateurs permet de définir une forme </li></ul><ul><li>agréable pour des opérations sur des objets. </li></ul><ul><li>Complexe operator+(Complexe s, Complexe t) { </li></ul><ul><li>Complexe w; </li></ul><ul><li>w.re = s.re + t.re; </li></ul><ul><li>w.im = s.im + t.im; </li></ul><ul><li>return w; </li></ul><ul><li>} </li></ul><ul><li>On peut alors écrire : </li></ul><ul><li>Complexe a, b, c; </li></ul><ul><li>... </li></ul><ul><li>a = b + c; </li></ul>
    58. 58. <ul><li>Classes </li></ul><ul><li>1. Objectif </li></ul><ul><li>2. Déclaration </li></ul><ul><li>3. Définition </li></ul><ul><li>4. Encapsulation </li></ul><ul><li>5. Constructeurs </li></ul><ul><li>6. Une classe de complexes </li></ul><ul><li>7. Une classe de rationnels </li></ul><ul><li>8. Surcharge d'opérateurs </li></ul><ul><li>9. Liste d'initialisation </li></ul><ul><li>10. Membres statiques </li></ul><ul><li>11. Méthodes constantes </li></ul><ul><li>12. La classe string </li></ul>
    59. 59. Objectifs <ul><li>Une classe est la description d'une famille </li></ul><ul><li>d'objets ayant même structure et même </li></ul><ul><li>comportement. </li></ul><ul><li>Une classe regroupe un ensemble d'attributs </li></ul><ul><li>ou membres, répartis en </li></ul><ul><li>*un ensemble de données </li></ul><ul><li>*un ensemble de fonctions, appelées méthodes. </li></ul>
    60. 60. <ul><li>Avantages !!! </li></ul><ul><li>* simplifie l'utilisation des objets, </li></ul><ul><li>* rapproche les données et leur traitement: c'est l'objet qui sait le mieux comment gérer une demande, </li></ul><ul><li>* renforce la robustesse du programme et la structure </li></ul><ul><li>* simplifie la maintenance et la construction </li></ul><ul><li>* permet l'encapsulation : possibilité de ne montrer de l'objet que ce qui est nécessaire à son utilisation. </li></ul><ul><li>* (permet de) masquer l'implémentation </li></ul>
    61. 61. <ul><li>La déclaration d'une classe donne la nature des </li></ul><ul><li>membres (type, signature), et les droits d'accès: </li></ul><ul><li>public, protected, private (défaut). </li></ul><ul><li>La définition d'une classe fournit la définition des </li></ul><ul><li>méthodes. </li></ul><ul><li>L'encapsulation peut se pratiquer en donnant à </li></ul><ul><li>l'utilisateur </li></ul><ul><li>* un fichier en-tête contenant la déclaration de la classe; </li></ul><ul><li>* un module objet contenant la version compilée du fichier contenant la définition de la classe. </li></ul>
    62. 62. Déclaration <ul><li>La syntaxe est celle des structures. Une struct est une </li></ul><ul><li>classe dont tous les attributs sont publics. </li></ul><ul><li>class Point { </li></ul><ul><li>int x, y; </li></ul><ul><li>public: </li></ul><ul><li>void setPoint (int, int); </li></ul><ul><li>void deplace (int, int); </li></ul><ul><li>void affiche (); </li></ul><ul><li>}; </li></ul><ul><li>* La classe Point a deux membres données privés x et y. </li></ul><ul><li>* Elle a trois méthodes publiques setPoint, deplace et </li></ul><ul><li>affiche. </li></ul>
    63. 63. Définition <ul><li>L' opérateur de portée :: indique la classe à </li></ul><ul><li>laquelle appartient la méthode. </li></ul><ul><li>void Point::setPoint(int a, int b) { </li></ul><ul><li>x = a; y = b ; </li></ul><ul><li>} </li></ul><ul><li>void Point::deplace (int dx ,int dy) { </li></ul><ul><li>x += dx; y += dy; </li></ul><ul><li>} </li></ul><ul><li>void Point::affiche() { </li></ul><ul><li>cout << &quot;x = &quot; << x <<&quot; , y = &quot; << y << endl; </li></ul><ul><li>} </li></ul>
    64. 64. <ul><li>Les champs x, y invoqués dans les </li></ul><ul><li>méthodes sont ceux de l'objet qui appelle la </li></ul><ul><li>méthode. </li></ul><ul><li>Cet objet est explicitement accessible par le </li></ul><ul><li>pointeur this. On peut écrire </li></ul><ul><li>void Point::setPoint(int a, int b) { </li></ul><ul><li>this -> x = a; this -> y = b ; </li></ul><ul><li>} </li></ul>
    65. 65. Utilisation <ul><li>void main() { </li></ul><ul><li>Point a, b; </li></ul><ul><li>a.setPoint(1, 2); </li></ul><ul><li>b.setPoint(3,-5); </li></ul><ul><li>a.affiche(); // x = 1, y = 2 </li></ul><ul><li>b.affiche(); // x = 3, y = -5 </li></ul><ul><li>a.deplace(1,1); </li></ul><ul><li>a.affiche(); // x = 2, y = 3 </li></ul><ul><li>} </li></ul>
    66. 66. Encapsulation <ul><li>Principe de programmation : </li></ul><ul><li>Il s'agit de ne montrer à l'utilisateur que ce qui lui est destiné. </li></ul><ul><li>* seules des fonction d'accès et de modification sont rendues publiques; </li></ul><ul><li>* toute donnée est privée ou protégée; </li></ul><ul><li>* l'implémentation peut n‘être disponible que par un module objet. </li></ul><ul><li>Exemple: </li></ul><ul><li>Le projet est composé de trois fichiers </li></ul><ul><li>* Un fichier point.h de déclaration de la classe Point </li></ul><ul><li>* Un fichier point.c d'implémentation des méthodes de la classe </li></ul><ul><li>* Un fichier main.c d'utilisation. </li></ul><ul><li>Le fichier d'implémentation est à terme remplacé par un </li></ul><ul><li>module objet point.o </li></ul>
    67. 67. // Fichier main.c #include &quot;point.h&quot; void main() { Point a(1,2), b(3,-5); a.affiche(); b.affiche(); a.deplace(1,1); a.affiche(); } // Fichier point.h class Point { int x, y; public: Point (int, int); void deplace (int, int); void affiche (); }; // Fichier point.c #include <iostream.h> #include &quot;point.h&quot; Point::Point(int a, int b) { x = a; y = b ; } void Point::deplace (int dx , int dy) { x += dx; y += dy; } void Point::affiche() { cout << &quot;x = &quot; << x <<&quot; , y = &quot;<< y << endl; }
    68. 68. Constructeurs <ul><li>Les constructeurs permettent de définir les initialisations </li></ul><ul><li>possible des instances d'une classe. </li></ul><ul><li>* En C++, un constructeur a le nom de la classe, et pas de </li></ul><ul><li>type de retour. </li></ul><ul><li>* Une classe peut avoir plusieurs constructeurs. </li></ul><ul><li>* Un constructeur sans arguments est appelé constructeur </li></ul><ul><li>par défaut. </li></ul><ul><li>- ce constructeur existe implicitement, s'il est le seul </li></ul><ul><li>constructeur. </li></ul><ul><li>- la définition d'un deuxième constructeur exige que l'on </li></ul><ul><li>définisse explicitement le constructeur par défaut si l'on </li></ul><ul><li>veut s'en servir. </li></ul>
    69. 69. <ul><li>Le constructeur par défaut est utilisé </li></ul><ul><li>* lors de la définition d'un objet, par </li></ul><ul><li>X x; </li></ul><ul><li>* lors d'une allocation, par </li></ul><ul><li>px = new X; </li></ul><ul><li>Sauf écriture explicite, le constructeur par </li></ul><ul><li>défaut n'effectue pas d'action. </li></ul>
    70. 70. Destructeur <ul><li>Le destructeur est noté ~X() pour une classe X. </li></ul><ul><li>Il est utilisé </li></ul><ul><li>* lorsque le programme quitte le bloc où l'objet est déclaré </li></ul><ul><li>* pour la destruction explicite par delete px; </li></ul><ul><li>Le destructeur permet de spécifier ce qui doit être </li></ul><ul><li>fait quand l'objet est désalloué. Ceci est important </li></ul><ul><li>quand un constructeur fait de l'allocation explicite. </li></ul>
    71. 71. Exemple constructeur <ul><li>Remplacement de la méthode setPoint par un constructeur : </li></ul><ul><li>class Point { </li></ul><ul><li>int x, y; </li></ul><ul><li>public: </li></ul><ul><li>Point (int, int); </li></ul><ul><li>void deplace (int, int); </li></ul><ul><li>void affiche (); </li></ul><ul><li>}; </li></ul><ul><li>Le constructeur Point(int,int) rend inopérant le constructeur par défaut </li></ul><ul><li>s'il n'est pas redéfini. </li></ul><ul><li>Le constructeur est employé en passant les arguments en paramètre. </li></ul><ul><li>C'est une abréviation de </li></ul><ul><li>Point a = Point(1.5,2.5), b = Point(3,-5); </li></ul><ul><li>Point::Point(int a, int b) { </li></ul><ul><li>x = a; y = b ; </li></ul><ul><li>}... </li></ul><ul><li>void main() </li></ul><ul><li>{ Point a(1.5,2.5), b(3,-5); </li></ul><ul><li>... </li></ul><ul><li>} </li></ul>
    72. 72. <ul><li>Variations </li></ul><ul><li>* Un constructeur simple peut être défini en ligne, </li></ul><ul><li>par </li></ul><ul><li>class Point { </li></ul><ul><li>int x, y; </li></ul><ul><li>public: </li></ul><ul><li>Point (int a, int b) {x = a; y = b;} </li></ul><ul><li>... </li></ul><ul><li>}; </li></ul><ul><li>* Au lieu de construire l'objet puis d'affecter des </li></ul><ul><li>valeurs aux champs, on peut initialiser les champs </li></ul><ul><li>avec les valeurs, par </li></ul><ul><li>Point (int a, int b) : x(a), y(b) {} </li></ul>
    73. 73. Tableaux d'Objets <ul><li>Tableaux d'objets attention le constructeur par défaut est </li></ul><ul><li>appelé sur chaque élément du tableau. </li></ul><ul><li>main () { </li></ul><ul><li>const int taille = 7; </li></ul><ul><li>Point* a = new Point[taille]; // par defaut </li></ul><ul><li>for (int i=0; i < taille ; i++) </li></ul><ul><li>cout << i << a[i].x << a[i].y << endl; </li></ul><ul><li>delete [] a; </li></ul><ul><li>} </li></ul><ul><li>La libération d'un tableau d'objets par delete [] </li></ul><ul><li>* parcourt le tableau et appelle le destructeur sur chaque élément du tableau; </li></ul><ul><li>* puis libère le tableau. </li></ul>
    74. 74. Construction&Destruction <ul><li>La mention explicite du constructeur par défaut et du destructeur </li></ul><ul><li>signifie leur redéfinition. </li></ul><ul><li>class Id { </li></ul><ul><li>string nom; </li></ul><ul><li>public: </li></ul><ul><li>Id() { cout << &quot;Entrez votre nom : &quot;;cin >> nom;} </li></ul><ul><li>~Id(){ cout <<&quot;Mon nom est &quot;<< nom <<endl; } </li></ul><ul><li>}; </li></ul><ul><li>Le programme se réduit à: </li></ul><ul><li>void main() </li></ul><ul><li>{ </li></ul><ul><li>Id pierre, paul; </li></ul><ul><li>} </li></ul><ul><li>Voici une trace d'exécution: </li></ul><ul><li>Entrez votre nom : Pierre </li></ul><ul><li>Entrez votre nom : Paul </li></ul><ul><li>Mon nom est Paul </li></ul><ul><li>Mon nom est Pierre </li></ul>Ou: Id pierre,paul; void main(){}
    75. 75. Une classe de Complexes <ul><li>class Complexe { </li></ul><ul><li>double re, im; </li></ul><ul><li>public: </li></ul><ul><li>Complexe() { re = im = 0;} </li></ul><ul><li>Complexe(double , double ) ; </li></ul><ul><li>Complexe(double x) ; </li></ul><ul><li>}; </li></ul><ul><li>Complexe::Complexe(double x, double y) {re = x; im = y;} </li></ul><ul><li>Complexe::Complexe(double x) {re = x; im = 0;} </li></ul><ul><li>Si les fonctions sont courtes, on les définit en ligne. Ensemble: </li></ul><ul><li>class Complexe { </li></ul><ul><li>double re, im; </li></ul><ul><li>Complexe() { re = im = 0;} </li></ul><ul><li>Complexe(double x, double y) {re = x; im = y;} </li></ul><ul><li>Complexe(double x) {re = x; im = 0;} </li></ul><ul><li>} </li></ul><ul><li>Le constructeur par défaut Complexe() est explicité pour </li></ul><ul><li>fixer des valeurs de départ. Ainsi </li></ul><ul><li>Complexe s, t; </li></ul><ul><li>définit deux complexes s, t initialisés à zéro. </li></ul>
    76. 76. <ul><li>En utilisant les arguments par défaut, les trois </li></ul><ul><li>constructeurs se réduisent en un seul. </li></ul><ul><li>Ici, on remplace l'affectation par l'initialisation, et on ajoute </li></ul><ul><li>une méthode: </li></ul><ul><li>class Complexe { </li></ul><ul><li>double re, im; </li></ul><ul><li>Complexe(double r = 0, double i = 0) : re(r), im(i) {} </li></ul><ul><li>double getModule() { return sqrt(re*re + im*im); } </li></ul><ul><li>} </li></ul><ul><li>On s'en sert </li></ul><ul><li>* à l'initialisation, par exemple </li></ul><ul><li>Complexe h, a(3,5), b = Complexe(2,4); </li></ul><ul><li>Complexe c(5), d = Complexe(6), e = 7; </li></ul><ul><li>Par conversion de type, 7 est transformé en Complexe(7) </li></ul><ul><li>puis copié. </li></ul>
    77. 77. Une interface plus complète <ul><li>La déclaration est: </li></ul><ul><li>#include <iostream.h> </li></ul><ul><li>#include <math.h> </li></ul><ul><li>class Complexe { </li></ul><ul><li>public : </li></ul><ul><li>Complexe(double re = 0, double im = 0); </li></ul><ul><li>double getRe(); </li></ul><ul><li>double getIm(); </li></ul><ul><li>double getModule(); </li></ul><ul><li>void setRe(double); </li></ul><ul><li>void setIm(double); </li></ul><ul><li>void showXY() { cout << getRe() << &quot; &quot; << getIm() <<&quot; &quot;; } </li></ul><ul><li>private: </li></ul><ul><li>double re, im; // Premiere implementation </li></ul><ul><li>} </li></ul>
    78. 78. <ul><li>// Implémentation </li></ul><ul><li>Complexe::Complexe(double re, double im): re(re), im(im){} </li></ul><ul><li>double Complexe::getRe() { return re; } </li></ul><ul><li>double Complexe::getIm() { return im; } </li></ul><ul><li>double Complexe::getModule() { return sqrt(re*re+im*im); } </li></ul><ul><li>void Complexe::setRe(double x) { re = x; } </li></ul><ul><li>void Complexe::setIm(double y) { im = y; } </li></ul><ul><li>// Utilisation </li></ul><ul><li>void main() </li></ul><ul><li>{ </li></ul><ul><li>Complexe a = Complexe(3,4); </li></ul><ul><li>cout << a.getModule() << endl; </li></ul><ul><li>a.showXY(); </li></ul><ul><li>a.setRe(20); </li></ul><ul><li>a.setIm(20); </li></ul><ul><li>cout << a.getModule() << endl; </li></ul><ul><li>a.showXY(); </li></ul><ul><li>Complexe b(5); </li></ul><ul><li>cout << b.getModule() << endl; </li></ul><ul><li>b.showXY(); </li></ul>
    79. 79. Les rationnels <ul><li>L'objectif est de montrer l'utilisation de surcharges, </li></ul><ul><li>cette fois-ci sur les opérateurs arithmétiques et d'entrée-sortie. </li></ul><ul><li>½ -3547/977777 0/1 etc </li></ul><ul><li>Un nombre rationnel est toujours réduit, et le </li></ul><ul><li>dénominateur est toujours strictement positif. D'où </li></ul><ul><li>la nécessité d'une méthode de réduction. </li></ul><ul><li>[réduit: numérateur et dénominateur sont des </li></ul><ul><li>entiers premiers entre eux, c-a-d les plus petits </li></ul><ul><li>possibles.] </li></ul>
    80. 80. <ul><li>class Rat { </li></ul><ul><li>static int pgcd(int,int); </li></ul><ul><li>public: </li></ul><ul><li>int num, den; </li></ul><ul><li>void red(); // reduit la fraction </li></ul><ul><li>Rat(int n = 0) : num(n), den(1) {} </li></ul><ul><li>Rat(int n, int d) : num(n), den(d) </li></ul><ul><li>{ red();} </li></ul><ul><li>}; </li></ul><ul><li>La réduction fait appel à une fonction de calcul de pgcd: </li></ul><ul><li>void Rat::red() { int p = pgcd( (num > 0) ? num : -num, den); num /= p; den /= p; } </li></ul><ul><li>int Rat::pgcd(int a, int b) { return (!b) ? a : pgcd(b, a%b); } </li></ul><ul><li>Une méthode déclarée static ( Méthode de classe ) </li></ul><ul><li>* peut être appelée sans référence à une instance </li></ul><ul><li>* peut être appelée par référence à sa classe </li></ul><ul><li>* n'a pas de pointeur this associé. </li></ul><ul><li>Une donnée déclarée static ( Donnée de classe ) est commune à </li></ul><ul><li>toutes les instances, une seule allocation et donc une seule </li></ul><ul><li>valeur. </li></ul>
    81. 81. Exemple de Surcharge d'opérateurs <ul><li>Comme toute fonction, un opérateur peut également être surchargé. </li></ul><ul><li>Pour surcharger un opérateur op on définit une nouvelle fonction de </li></ul><ul><li>Nom operator op </li></ul><ul><li>Par exemple operator= ou operator+. </li></ul><ul><li>La syntaxe est </li></ul><ul><li>type operatorop(types des opérandes) { /* corp de l'opérateur */ return valeur; } </li></ul><ul><li>Par exemple </li></ul><ul><li>Rat operator+(Rat,Rat); </li></ul><ul><li>L'expression a+b est implicitement traduite par le compilateur en </li></ul><ul><li>operator+(a, b) </li></ul><ul><li>Un opérateur surchargé peut se définir </li></ul><ul><li>* au niveau global, </li></ul><ul><li>* comme membre d'une classe. </li></ul><ul><li>Apport de la surcharge: le calcul s'écrit comme pour un type </li></ul><ul><li>élémentaire ! </li></ul>
    82. 82. <ul><li>Nous définissons les quatre opérations arithmétiques par: </li></ul><ul><li>Rat operator+(Rat a, Rat b) { </li></ul><ul><li>return Rat(a.num*b.den + a.den*b.num, a.den*b.den); </li></ul><ul><li>} </li></ul><ul><li>Rat operator-(Rat a, Rat b) { </li></ul><ul><li>return Rat(a.num*b.den - a.den*b.num, a.den*b.den); </li></ul><ul><li>} </li></ul><ul><li>Rat operator/(Rat a, Rat b) { </li></ul><ul><li>return Rat(a.num*b.den, a.den*b.num); </li></ul><ul><li>} </li></ul><ul><li>Rat operator*(Rat a, Rat b) { </li></ul><ul><li>return Rat(a.num*b.num, a.den*b.den); </li></ul><ul><li>} </li></ul><ul><li>Le moins unaire se définit par: </li></ul><ul><li>Rat operator-(Rat a) { </li></ul><ul><li>return Rat(-a.num, a.den); </li></ul><ul><li>} </li></ul>
    83. 83. <ul><li>Les rationnels passé en argument ne sont pas modifiés, on peut donc </li></ul><ul><li>les spécifier const Rat&. </li></ul><ul><li>Rat operator+(const Rat& a, const Rat& b) {...} </li></ul><ul><li>Rat operator-(const Rat& a, const Rat& b) {...} </li></ul><ul><li>... </li></ul><ul><li>L'opérateur d'incrémentation += se surcharge également: </li></ul><ul><li>Rat& operator+=(Rat& a, const Rat& b) { </li></ul><ul><li>a.num = a.num*b.den + a.den*b.num; </li></ul><ul><li>a.den = a.den*b.den; a.red(); </li></ul><ul><li>return a; </li></ul><ul><li>} </li></ul><ul><li>L'un des appels </li></ul><ul><li>a += b; //ou </li></ul><ul><li>operator+=(a,b); </li></ul><ul><li>* construit dans a passé par référence, la valeur incrémentée, </li></ul><ul><li>* et en transmet la référence en sortie. </li></ul><ul><li>Ici, une définition en méthode est plus logique </li></ul>
    84. 84. Donnée membre statique <ul><li>Une donnée membre statique est spécifiée </li></ul><ul><li>par static. </li></ul><ul><li>* Elle n'est instanciée qu'une seule fois; </li></ul><ul><li>* Elle est commune à toutes les instances </li></ul><ul><li>de la classe; </li></ul><ul><li>* Si un objet la modifie, elle est modifiée </li></ul><ul><li>pour tous les objets. </li></ul><ul><li>* Elle est initialisée avant utilisation. </li></ul>
    85. 85. Exemple de donnée statique <ul><li>#include <iostream.h> </li></ul><ul><li>class XY { </li></ul><ul><li>public: </li></ul><ul><li>static int app; </li></ul><ul><li>XY() { cout << &quot;+ : &quot; << ++app << endl; } </li></ul><ul><li>~XY() { cout << &quot;- : &quot;<< app-- << endl; } </li></ul><ul><li>}; </li></ul><ul><li>int XY::app = 0; // initialisation globale </li></ul><ul><li>void main() { </li></ul><ul><li>XY a, b, c; </li></ul><ul><li>{ </li></ul><ul><li>XY a, b; </li></ul><ul><li>} </li></ul><ul><li>XY d; </li></ul><ul><li>} </li></ul><ul><li>Résultat: </li></ul><ul><li>+ : 1 </li></ul><ul><li>+ : 2 </li></ul><ul><li>+ : 3 </li></ul><ul><li>+ : 4 </li></ul><ul><li>+ : 5 </li></ul><ul><li>- : 5 </li></ul><ul><li>- : 4 </li></ul><ul><li>+ : 4 </li></ul><ul><li>- : 4 </li></ul><ul><li>- : 3 </li></ul><ul><li>- : 2 </li></ul><ul><li>- : 1 </li></ul>
    86. 86. Copie et affectation <ul><li>1. Constructeurs </li></ul><ul><li>2. Constructeur de copie </li></ul><ul><li>3. Affectation </li></ul><ul><li>4. Conversions </li></ul><ul><li>La copie et l'affectation sont des opération </li></ul><ul><li>très importante. </li></ul>
    87. 87. Constructeurs <ul><li>Les constructeurs se classent syntaxiquement </li></ul><ul><li>en 4 catégories </li></ul><ul><li>1. le constructeur par défaut, sans argument, </li></ul><ul><li>2. les constructeurs de conversion, à un </li></ul><ul><li>argument </li></ul><ul><li>3. le constructeur de copie, à un argument </li></ul><ul><li>4. les autres constructeurs. </li></ul>
    88. 88. constructeur de conversion <ul><li>Un constructeur de conversion sert souvent à la promotion. </li></ul><ul><li>Exemple: </li></ul><ul><li>class Rat { </li></ul><ul><li>int num, den; </li></ul><ul><li>public: </li></ul><ul><li>... </li></ul><ul><li>Rat(int n) { num = n; den = 1;} </li></ul><ul><li>... </li></ul><ul><li>}; </li></ul><ul><li>On s'en sert pour la conversion </li></ul><ul><li>Rat r, s; </li></ul><ul><li>... </li></ul><ul><li>r = s + 7; </li></ul><ul><li>L'entier 7 est promu en Rat(7) avant l'addition. </li></ul>
    89. 89. Constructeur de copie <ul><li>Chaque classe possède un constructeur de copie </li></ul><ul><li>(ne pas confondre avec l'opérateur d'affectation). </li></ul><ul><li>Le constructeur de copie par défaut copie membre </li></ul><ul><li>à membre en utilisant le constructeur de copie de </li></ul><ul><li>chaque membre, et une copie bit à bit pour les types </li></ul><ul><li>de base (copie superficielle). Ceci est insuffisant en </li></ul><ul><li>présence d'adresses. Il faut alors allouer de </li></ul><ul><li>nouvelles zones mémoire (copie profonde). </li></ul>
    90. 90. <ul><li>Le constructeur de copie est utilisé </li></ul><ul><li>* lors d'une initialisation: </li></ul><ul><li>X x = y; </li></ul><ul><li>X x(y); </li></ul><ul><li>X* x = new X(y); </li></ul><ul><li>où y est un objet déjà existant. </li></ul><ul><li>* lors du retour d'une fonction retournant un objet par valeur; </li></ul><ul><li>* lors du passage d'un objet par valeur à une fonction. </li></ul><ul><li>Le constructeur de copie a deux prototypes possibles : </li></ul><ul><li>X (X&); </li></ul><ul><li>X (const X&); </li></ul><ul><li>L'argument est donc un objet de la classe X passé par </li></ul><ul><li>référence (évidemment !) et éventuellement spécifié comme </li></ul><ul><li>Non modifiable dans le constructeur. </li></ul>
    91. 91. <ul><li>Voici une classe Pt possédant: </li></ul><ul><li>* Un constructeur de copie Pt(const Pt& p) </li></ul><ul><li>* Un opérateur d'affectation Pt& operator=(const Pt& p) </li></ul><ul><li>#include <iostream.h> </li></ul><ul><li>class Pt { </li></ul><ul><li>int x, y; </li></ul><ul><li>public: </li></ul><ul><li>Pt(int abs = 1, int ord = 0): x(abs), y(ord) {} </li></ul><ul><li>//implantation par défaut: </li></ul><ul><li>Pt(const Pt& p) : x(p.x), y(p.y){} </li></ul><ul><li>//implantation par défaut: </li></ul><ul><li>Pt& operator=(const Pt& p) { </li></ul><ul><li>x = p.x; y = p.y; </li></ul><ul><li>return *this; </li></ul><ul><li>} </li></ul><ul><li>}; </li></ul>
    92. 92. Affectation <ul><li>L'affectation et la copie sont des opérations différentes. </li></ul><ul><li>* le constructeur de copie sert à l'initialisation et pour le passage de paramètres. Il construit l'objet. </li></ul><ul><li>* l'opérateur d'affectation = pour l'affectation dans une expression. Il retourne un objet ou une référence. </li></ul><ul><li>L'opérateur d'affectation est un opérateur, et peut donc être </li></ul><ul><li>redéfini explicitement par une fonction operator=(). </li></ul><ul><li>Chaque classe possède un opérateur d'affectation par </li></ul><ul><li>défaut. </li></ul><ul><li>L'affectation est superficielle comme la copie, et consiste </li></ul><ul><li>en une affectation membre à membre. </li></ul>
    93. 93. <ul><li>La signature de l'opérateur est </li></ul><ul><li>X& operator=(X&) </li></ul><ul><li>X& operator=(const X&) </li></ul><ul><li>X operator=(X&) </li></ul><ul><li>X operator=(const X&) </li></ul><ul><li>et l'expression y = x équivaut à </li></ul><ul><li>y.operator=(x) </li></ul><ul><li>Le résultat de l'affectation est donc dans </li></ul><ul><li>l'objet appelant. </li></ul>
    94. 94. Fonctions amies <ul><li>L'amitié permet d'accéder aux parties privées. </li></ul><ul><li>Une ''déclaration d'amitié'' incorpore, dans une classe X, </li></ul><ul><li>les fonctions autorisées à accéder aux membres privés. </li></ul><ul><li>Une fonction amie a le même statut qu'une fonction </li></ul><ul><li>membre de X. </li></ul><ul><li>Fonction globale </li></ul><ul><li>class X { ... </li></ul><ul><li>friend f(X); </li></ul><ul><li>} </li></ul><ul><li>Ici, f est autorisée à accéder aux membres privés de la </li></ul><ul><li>classe X. </li></ul>
    95. 95. <ul><li>Fonction membre de Y </li></ul><ul><li>class Y { ... </li></ul><ul><li>void f(X& x); </li></ul><ul><li>} </li></ul><ul><li>class X { ... </li></ul><ul><li>friend Y::f(X& x); </li></ul><ul><li>} </li></ul><ul><li>void Y::f(X& x) { </li></ul><ul><li>x.priv = 1; // ok </li></ul><ul><li>x.prot = 1; // ok </li></ul><ul><li>x.publ = 1; // ok </li></ul><ul><li>} </li></ul><ul><li>Une classe entière est une classe amie par </li></ul><ul><li>class X { ... </li></ul><ul><li>friend class Y; </li></ul><ul><li>} </li></ul>
    96. 96. Opérateurs amis <ul><li>Une fonction amie d'une classe a les mêmes droits qu'une </li></ul><ul><li>fonction membre, et en particulier peut accéder aux </li></ul><ul><li>membres privés de la classe. </li></ul><ul><li>class Rat { </li></ul><ul><li>int num, den; // prives </li></ul><ul><li>public: </li></ul><ul><li>int getNum() {return num;} </li></ul><ul><li>int getDen() {return den;} </li></ul><ul><li>Rat(int n = 0, int d = 1) : num(n), den(d) {} </li></ul><ul><li>}; </li></ul>
    97. 97. <ul><li>L'addition </li></ul><ul><li>Rat operator+(const Rat& a, const Rat& b) { </li></ul><ul><li>int n = a.getNum()*b.getDen() + a.getDen()*b.getNum(); </li></ul><ul><li>return Rat(n, a.getDen()*b.getDen()); </li></ul><ul><li>} </li></ul><ul><li>s'écrit plus efficacement et plus lisiblement: </li></ul><ul><li>Rat operator+(const Rat& a, const Rat& b) { </li></ul><ul><li>return Rat(a.num*b.den + a.den* b.num, a.den*b.den); </li></ul><ul><li>} </li></ul><ul><li>Or num et den sont privés. Pour les rendre accessibles, </li></ul><ul><li>l'opérateur est déclaré ami, dans la déclaration de la classe </li></ul><ul><li>Rat, par </li></ul><ul><li>friend Rat operator+(Rat, Rat); </li></ul><ul><li>Une fonction amie a les mêmes droits qu'une fonction </li></ul><ul><li>membre. </li></ul>
    98. 98. Syntaxe <ul><li>Un opérateur est unaire, binaire. </li></ul><ul><li>Un opérateur peut être défini </li></ul><ul><li>* soit comme fonction globale à un ou deux arguments </li></ul><ul><li>* soit comme fonction membre avec un argument de moins. </li></ul><ul><li>La syntaxe est </li></ul><ul><li>* opérateur binaire au niveau global: </li></ul><ul><li>type operatorop(type,type); </li></ul><ul><li>Rat operator+(Rat,Rat); </li></ul><ul><li>L'expression u+v équivaut à operator+(u,v). </li></ul><ul><li>* opérateur binaire membre de classe: </li></ul><ul><li>type operatorop(type); </li></ul><ul><li>Rat& operator+=(Rat); </li></ul><ul><li>L'expression u += v équivaut à u.operator+=(v). </li></ul>
    99. 99. <ul><li>* opérateur unaire au niveau global: </li></ul><ul><li>type operatorop(type); </li></ul><ul><li>Rat operator-(Rat); </li></ul><ul><li>L'expression -u équivaut à operator-(u). </li></ul><ul><li>* opérateur unaire membre de classe: </li></ul><ul><li>type operatorop(); </li></ul><ul><li>Rat operator-(); </li></ul><ul><li>L'expression -u équivaut à u.operator-(). </li></ul>
    100. 100. Un Conseil <ul><li>* Choisir un opérateur global et ami lorsque l'opération est symétrique: + - * / == </li></ul><ul><li>* Choisir un opérateur membre lorsque l'opération est asymétrique ou nécessite une référence : += </li></ul><ul><li>class Rat { </li></ul><ul><li>int num, den; </li></ul><ul><li>public: </li></ul><ul><li>... </li></ul><ul><li>Rat operator-(Rat); //membre : mauvais choix </li></ul><ul><li>Rat& operator+=(const Rat&); //membre :bon choix </li></ul><ul><li>friend Rat operator/(Rat , Rat ); //amie : bon choix </li></ul><ul><li>}; </li></ul>
    101. 101. <ul><li>Avec </li></ul><ul><li>Rat Rat::operator-(Rat b) {return Rat(num*b.den - den* b.num, den*b.den);} </li></ul><ul><li>Rat& Rat::operator+=(const Rat& d) { </li></ul><ul><li>num = num*d.den + d.num*den; </li></ul><ul><li>den = den*d.den; </li></ul><ul><li>return *this; </li></ul><ul><li>} </li></ul><ul><li>Rat operator/(Rat a, Rat b) { </li></ul><ul><li>return Rat(a.num*b.den, a.den*b.num); </li></ul><ul><li>} </li></ul><ul><li>Exemple </li></ul><ul><li>cout << a << b << a-b << a.operator-(b) </li></ul><ul><li><< a-1 << a+=2 << a; </li></ul><ul><li>Résultat </li></ul><ul><li>1/2 2/3 -1/6 -1/6 -1/2 3/2 3/2 </li></ul>
    102. 102. Héritage <ul><li>1. Objectif </li></ul><ul><li>2. Classe composée ou classe dérivée </li></ul><ul><li>3. Syntaxe </li></ul><ul><li>4. Accès aux données et méthodes </li></ul><ul><li>5. Classes dérivées et constructeurs </li></ul><ul><li>6. Héritage multiple </li></ul>
    103. 103. Objectif <ul><li>L'héritage est l'un des principes fondamentaux de la </li></ul><ul><li>programmation objet. Il a pour objectif de hiérarchiser </li></ul><ul><li>les classes et les objets. </li></ul><ul><li>L'héritage est mis en oeuvre par la construction de </li></ul><ul><li>classes dérivées. Une classe dérivée </li></ul><ul><li>* contient les données membres de sa classe de base; </li></ul><ul><li>* peut en ajouter de nouvelles; </li></ul><ul><li>* possède a priori les méthodes de sa classe de base; </li></ul><ul><li>* peut redéfinir (masquer) certaines méthodes; </li></ul><ul><li>* peut ajouter de nouvelles méthodes. </li></ul><ul><li>L'héritage peut être simple ou multiple. </li></ul>
    104. 104. Avantages: <ul><li>* Une classe dérivée modélise un cas particulier </li></ul><ul><li>de la classe de base, et peut donc utiliser la classe </li></ul><ul><li>de base; </li></ul><ul><li>* l'héritage encourage la recherche de la généralité et de la généricité; </li></ul><ul><li>* une hiérarchie de classes facilite la solution de problèmes complexes; </li></ul><ul><li>* facilite la maintenance, le développement et les extensions; </li></ul><ul><li>* peut ajouter de nouvelles méthodes. </li></ul>
    105. 105. Composition ou Héritage <ul><li>Une classe est composée si certains de ses membres sont eux-mêmes des objets. </li></ul><ul><li>class DescrHabitant { </li></ul><ul><li>protected: </li></ul><ul><li>string nom; </li></ul><ul><li>string domicile; </li></ul><ul><li>}; </li></ul><ul><li>La description d'un habitant fait partie d'une carte d'identité; correct car une </li></ul><ul><li>carte d'identité n'est pas un cas particulier d'un habitant. </li></ul><ul><li>class DescrResident : public DescrHabitant{ </li></ul><ul><li>protected: </li></ul><ul><li>string residence; </li></ul><ul><li>}; </li></ul><ul><li>La description d'un résident est plus complète que celle d'un habitant: </li></ul><ul><li>l'information supplémentaire est l'adresse de sa résidence (qui peut être </li></ul><ul><li>différente de celle de son domicile). </li></ul>class Carte { DescrHabitant h; int age; float age; };
    106. 106. Syntaxe <ul><li>La syntaxe pour la définition d'une classe dérivée est </li></ul><ul><li>class classe_derivee : protection classe_de_base </li></ul><ul><li>{...}; </li></ul><ul><li>Les types de protection sont public, protected, </li></ul><ul><li>private. </li></ul><ul><li>En général, on choisit public. </li></ul>
    107. 107. Des Exemples <ul><li>* Une voiture comporte quatre (ou cinq) roues, donc </li></ul><ul><li>class Automobile { </li></ul><ul><li>Roue roues[5]; </li></ul><ul><li>... </li></ul><ul><li>} </li></ul><ul><li>* Un segment comporte deux points; </li></ul><ul><li>* Un anneau est un cas particulier d'un cercle; </li></ul><ul><li>* Une forme contient un rectangle englobant: </li></ul><ul><li>class Shape { </li></ul><ul><li>Rect r; </li></ul><ul><li>... </li></ul><ul><li>} </li></ul><ul><li>* Un triangle est une forme particulière: </li></ul><ul><li>class Triangle : public Shape { </li></ul><ul><li>... </li></ul><ul><li>} </li></ul><ul><li>Discussion : un carré est-il un cas particulier d'un rectangle ? </li></ul>
    108. 108. Accès aux données et méthodes <ul><li>Les attributs de la classe de base peuvent être désignés directement </li></ul><ul><li>ou par le nom de la classe de base, en employant l'opérateur de portée </li></ul><ul><li>:: </li></ul><ul><li>class DescrHabitant { </li></ul><ul><li>string nom; </li></ul><ul><li>string domicile; </li></ul><ul><li>public: </li></ul><ul><li>DescrHabitant(); </li></ul><ul><li>void show(); </li></ul><ul><li>}; </li></ul><ul><li>class DescrResidence : public DescrHabitant { </li></ul><ul><li>string residence; </li></ul><ul><li>public: </li></ul><ul><li>DescrResidence(); </li></ul><ul><li>void show(); </li></ul><ul><li>}; </li></ul>
    109. 109. Implantations <ul><li>DescrHabitant::DescrHabitant() { </li></ul><ul><li>cout << &quot;Entrez votre nom : &quot;; cin >> nom; </li></ul><ul><li>cout << &quot;Entrez votre domicile : &quot;; cin >> domicile; </li></ul><ul><li>} </li></ul><ul><li>void DescrHabitant::show() { </li></ul><ul><li>cout << &quot;Nom: tt&quot; << nom << endl; </li></ul><ul><li>cout << &quot;Domicile t&quot; << domicile << endl; </li></ul><ul><li>} </li></ul><ul><li>DescrResidence::DescrResidence() { </li></ul><ul><li>// appel implicite du constructeur par défaut de la classe de base. </li></ul><ul><li>cout << &quot;Entrez votre residence : &quot;; cin >> residence; </li></ul><ul><li>} </li></ul><ul><li>void DescrResidence::show() { </li></ul><ul><li>DescrHabitant::show() ; // l'appel de la méthode de la classe de base. </li></ul><ul><li>cout << &quot;Residence t&quot; << residence << endl; </li></ul>
    110. 110. Héritage multiple <ul><li>Une classe peut hériter de plusieurs </li></ul><ul><li>classes. Les classes de bases sont alors </li></ul><ul><li>énumérées dans la définition. </li></ul><ul><li>class D : public B1, public B2 {...} </li></ul>

    ×