Dans ce cours Organisation du cours – présentation des langages informatique par Patrick Bellot – ce qui est similaire à Java (révision ) – ce qui est différent de Java – interfaces graphiques Java Swing Deux langages support – C++: pour illustrer divers concepts, mécanismes et difficultés présents ?dans les langages courants – Java: pour comparer et pour illustrer la programmation événementielle Liens – – Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 2 | |
1972 : Langage C 1983 : Objective C 1985 : C++ 1991 : Python 1995 : Java 2001: C# 2011: C++11 2014: Swift | Brève historique (très parcellaire) Extension objet du C popularisée par NeXt puis Apple Syntaxe inhabituelle inspirée de Smalltalk Extension object du C par Bjarne Stroustrup aux Bell Labs Vise la simplicité/rapidité d'écriture, créé par G. van Rossum Interprété, typage dynamique Simplification du C++ de SunMicrosystems puis Oracle Egalement inspiré de Smalltalk, ADA A l'origine, le « Java de Microsoft» Egalement inspiré de Delphi, C++, etc. Révision majeure du C++, suivie de C++14 et C++17 Le successeur d'Objective C, par Apple | |
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 3 | |
C++ versus C et Java C++ = extension du langage C – un compilateur C++ peut compiler du C (avec qq restrictions) – un même programme peut combiner C, C++ et Objective C (Apple) ou C# (Windows) C++, Java, C# dérivent de la syntaxe du C – avec l’orienté objet et bien d’autres fonctionnalités Différences notables entre C++ et Java – gestion mémoire, héritage multiple, redéfinition des opérateurs, pointeurs de fonctions et de méthodes, passage des arguments, templates – programmes : • Java : à la fois compilés (byte code) puis interprétés ou compilés à la volée • C/C++ : compilés en code natif (et généralement plus rapides) Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 4 | |
Références et liens Livres, tutoriaux, manuels – Le langage C++, Bjarne Stroustrup (auteur du C++), Pearson – manuel de référence: ou –? faqs, aide: , , etc. – Cours C++ de Christian Casteyde: Liens – Travaux Pratiques de ce cours : – Petit tutoriel de Java à C++ (pas maintenu) : – Toolkit graphique Qt: – Extensions Boost: – Cours C++ de Christian Casteyde: – Site de B. Stroustrup: Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 5 |
Premier chapitre : Des objets et des classes Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 6 | |||
Programme C++ Constitué – de classes comme en Java – et, éventuellement, de fonctionsetvariables « non-membre » (= hors classes)?comme en C Bonne pratique : une classe principale par fichier – mais pas de contrainte syntaxique comme en Java
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 7 |
Déclarations et définitions C/C++ : deux types de fichiers – déclarations dans fichiers header (extension.h ou.hpp – définitions dans fichiers d’implémentation (.cpp) – en général à chaque .h correspond un .cpp En Java Car.h
– tout dans les .java | ou pas d'extension) Truck.h
| |||||
! |
| |||||
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 8 |
! !
!
!
!
!
!
!
! !
!
!
!
!
!
!
Instanciation Dans unautrefichier .cpp :
contient l'adresse ! de l'instance! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 16 | |
Instanciation Dans unautrefichier .cpp :
de l'instance! newcrée un objet (= une nouvelle instance de la classe) – 1) alloue la mémoire – 2) appelle le constructeur cest une variable locale qui pointe sur cet objet –? c est un pointeur (d'où l'*) qui contient l’adresse mémoire de l’instance 17 |
Pointeurs C/C++ vs. références Java C++
Javacontient l'adresse ! de l'instance! Pointeur C/C++ – variable qui contient une adresse mémoire – valeur accessible, arithmétique des pointeurs (calcul d'adresses bas niveau) Référence Java – variable qui contient l'adresse mémoire d'un objet (ou mécanisme équivalent) – valeur cachée, pas d'arithmétique Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 18 | |||
Pointeurs C/C++ vs. références Java C++
Javacontient l'adresse ! de l'instance!
Il n'y a pas de "magie", c'est à peu près la même chose (à part qu'il y a un ramasse-miettes en Java) 19 |
Accès aux variables et méthodes d'instance
L'opérateur->déréférence le pointeur – comme en C – mais . en Java Les méthodes d'instance – ont automatiquement accès aux variables d’instance Problème ? – sont toujoursappliquées à un objet Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 20 | ||||
Encapsulation
Problème –? radius est private => c n’a pas le droit d’y accéder 21 |
Encapsulation
Encapsulation – séparer la spécification de l'implémentation (concept de "boîte noire") – spécification: déclaration des méthodes • interface avec l’extérieur (API) => on ne peut interagir que via les méthodes – implémentation: variables et définition des méthodes • interne à l’objet => seul l'objet peut accéder à ses variables Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 22 |
Destruction des objets
deletedétruit l'objetpointépar le pointeur (pas le pointeur !) – 1) appelle le destructeur (s'il y en a un) ![]() – 2) libère la mémoire Rappel: pas deramasse miettesen C/C++ ! – sans delete l'objet continue d'exister jusqu’à la fin du programme – une solution : smart pointers (à suivre) 27 |
Destructeur / finaliseur
Methode appeléeAVANT?la destruction de l'objet Ne détruit pas l'objet ! – c'est delete qui le fait En C++ – méthode ~Circle() – les destructeurs sont chaînés (chaînage ascendant) En Java – méthode finalize() – les finaliseurs ne sont pas chaînés (et rarement utilisés) Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 28 | |
Destructeur / finaliseur
Sert à "faire le ménage" – fermer un fichier, une socket – détruire d'autres objets : ?ex: objet auxiliaire créé dans le constructeur En général il n'y en a pas ! – exple: ~Circle() ne sert à rien ! – note : les classes de basepolymorphes doivent avoir un destructeurvirtuel (à suivre) 29 |
Pointeurs nuls vs. pendants voidfoo(Circle* c) {! unsigned int area = 0;! if (c)area = c->getArea(); ! elseperror("Null pointer");! }! ! voidbar() {! Circle* c = newCircle(10, 20, 30);! foo(c);! deletec; // l'objet est détruit => c estpendant! c =nullptr; // c pointe surrien: OK!!foo(c); // OK car c est nulsinon plantage !! deletec; // OK car c est nul! }! Pointeur pendant =invalide ! – pointe sur un objet qui n'existe plus Pointeur nul = pointe sur rien – nullptr en C++ (autrefois:NULLou0) / null en Java Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 30 | ||||
Pointeurs nuls vs. pendants
deletec; // c estpendant = DANGER !!!! c =nullptr; // c pointe surrien=OK!! Pointeur pendant =invalide ! – pointe sur un objet qui n'existe plus Pointeur nul = pointe sur rien – nullptr en C++ (autrefois:NULLou0) / null en Java 31 |
!
!
!
!
!
!
!
!
!
!
!
Surcharge (overloading)
Fonctions ou méthodes – ayant le même nom mais des signatures différentes – pareil en Java Attention : méthodes d'unemêmeclasse ! – ne pas confondre avec laredéfinition de méthodes (overriding) ?dans une hiérarchie de classes Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 34 | ||
Paramètres par défaut
! Alternative à la surcharge – n'existe pas en Java – les valeurs par défaut doivent être à partir de la fin –? erreur de compilation s'il y a des ambiguïtés
! 35 |
!
Namespaces fichier math/Circle.h! fichier graph/Circle.h!
! !
namespace= espace de nommage – évitent les collisions de noms – similaires aux package de Java, existent aussi en C# Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 39 |
! !
Streams: entrées / sorties standard
Flux standards std = namespace de la bibliothèque standardstd::coutconsole out= sortie standard std::cerrconsole erreurs= sortie des erreurs (non bufferisées : affichage immédiat) std::cinconsole in= entrée standard 41 |
!
!
!
Retour sur les méthodes d'instance : où est la magie ?
Toujours appliquées à un objet : voidfoo() {! Circle* c = newCircle(100, 200, 35);! unsigned int r = c->getRadius();! unsigned int a =getArea(); // problème !!!! }! ! ! Mais pas la pourquoi ?! !unsigned intgetArea() const {! return PI *getRadius()*getRadius();! }! ! Comment la méthode accède à radius ?! !unsigned intgetRadius() const { ! returnradius; ! }! 45 |
! !
! !
! !
!
Documentation
Doxygen: documentation automatique – similaire à JavaDoc mais plus général (fonctionne avec de nombreux langages) – documentation : Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 47 |
Style et commentaires Règles • être cohérent • indenter (utiliser un IDE qui le fait automatiquement : TAB ou Ctrl-I en général) • aérer et passer à la ligne (éviter plus de 80 colonnes) • camelCase et mettre le nom des variables (pour la doc) • commenter quand c'est utile Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 48 | ||
Chapitre 2 : Héritage et polymorphisme Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 49 |
Héritage 2eConcept fondamental de l’OO Classe A
– les sous-classes héritentles méthodes et variables ?de leurs super-classes : • la classe B a une méthode foo() et une variablex – héritage simple • une classe ne peut hériter que d'une superclasse Classe B
– héritage multiple • une classe peut hériter de plusieurs classes • C++, Python, Eiffel, Java 8 – entre les deux • héritage multiple des interfaces • Java, C#, Objective C Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 50 |
!
!
!
ExempleRect classRect{! protected: ! int x, y;! unsigned int width, height;!
Squarepublic:! Rect();! Rect(int x, int y, unsigned int w, unsigned int h);! ! unsigned intgetWidth() const;! unsigned intgetHeight() const;! virtualvoidsetWidth(unsigned int w){width = w;}!virtualvoidsetHeight(unsigned int h){height = h;}! // etc ! };! !classSquare: publicRect{ ! public: ! Square();! Square(int x, int y, unsigned int size);! ! voidsetWidth(unsigned int w)override{width = height = w;}! sinon ce n'est! voidsetHeight(unsigned int h)override{width = height = h;}! plus un carré ! ! };! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 54 |
!
!
!
Remarques Chaînage des constructeurs Square::Square() :Rect() {}! chaînage explicite du constr. de la superclasse ! Square::Square() {}! chaînage implicite : fait la même chose ! Square::Square(int x, int y, unsigned int w) ! : Rect(x, y, w, w) { }! même chose que super()de Java
Covariance des types de retour – redéfinition de méthode => même signature – mais Muche peut-être une sous-classe de Truc Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 56 | |||||||
Classes de base
Shape.h
Circle.hRect.h
Erreur de compilation : Quel est le problème ? Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 57 |
! !
!
!
!
! !
! !
!
!
Directives du préprocesseur Header !inclut ce qui suit jusqu'à#endif! Truc.h! seulementsiTrucn'est pas déjà défini! définitTruc! -? doit êtreunique! ! -? => à forger sur nom du header ! Directives de compilation – #if/#ifdef/#ifndefpour compilation conditionnelle – #import(au lieu de #include) empêche l'inclusion multiple (mais pas standard) Headers – #include"Circle.h"cherche dans le répertoirecourant – #include<iostream>cherche dans les répertoiressystèmes (/usr/include, etc.) ?et dans ceux spécifiés par l'option -I du compilateur : gcc –Wall-I/usr/X11R6/include–o myprog! ! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 60 | ||
Polymorphisme d'héritage Rect
3econcept fondamentalde l’orienté objet – le plus puissant mais pas toujours le mieux compris ! Un objet peut être vu sous plusieurs formes
– un Square est aussi un Rect Square – mais l'inverse n'est pas vrai ! #include"Rect.h"! !voidfoo() {! Square* s = newSquare(); // s voit l'objet comme unSquare! Rect* r = s; // r voit objet comme unRect(upcastingimplicite)! ! Square* s2 = newRect(); // OK ?! Square* s3 = r; // OK ?! }! 61 | |||
Buts du polymorphisme Rect
Pouvoir choisir le point de vue le plus approprié ?selon les besoins Pouvoir traiter un ensemble de classes liées entre elles ? de manière uniforme sans considérer leurs détails Square
#include"Rect.h"! !voidfoo() {! Square* s = newSquare(); // s voit l'objet comme unSquare! Rect* r = s; // r voit objet comme unRect(upcastingimplicite)! ! Square* s2 = newRect(); // erreur de compilation!(downcastinginterdit !)! Square* s3 = r; // erreur de compilation!! }! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 62 |
!
Polymorphisme : Java Rect
Question à $1000 – quelle méthode setWidth() est appelée :?celle du pointeur ou celle du pointé ?
Rect* r = newSquare();! Squarer->setWidth(100);! ! Java – liaisondynamique /tardive : choix de la méthode à l'exécution ?? appelle toujours la méthode dupointé •? heureusement sinon le carré deviendrait un rectangle ! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 64 |
!
!
!
Règles à suivreShape Remarques • une redéfinition de méthode virtuelle ?est automatiquement virtuelle • une classe peut être finalRect
• attention :même signature ?sinon c'est de la surcharge ! Square
67 |
Règles à suivreShape Méthodes non virtuelles : dans quel cas ? • classepas héritée • méthodejamais redéfinie –?typiquement : getters et setters Rect
• méthode qu'on l'appelle très très très souvent : • appel un peu plus rapide –?généralement négligeable! –?gare aux erreurs !
Dans le doute on peut mettreSquarevirtualpartout et optimiser plus tard ! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 68 | |||||
Méthodes et classes abstraites
Méthodeabstraite – spécification d'un concept dont la réalisation diffère selon les sous-classes • pas implémentée • doit êtreredéfinieetimplémentée dans les sous-classes instanciables Classeabstraite – classe dont au moins une méthode est abstraite Java – pareil mais mot clé abstract Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 69 | ||||
Bénéfices des classes abstraites
Méthodeabstraite –? spécification d'un concept dont la réalisation diffère selon les sous-classes • pas implémentée • doit être redéfinie et implémentée dans les sous-classes instantiables
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 70 |
!
!
!
!
!
! !
Magie du polymorphisme
Remarque – cette fonction ignore l'existence de Circle, Rect, Square! Mission accomplie ! – on peut traiter un ensemble de classes liées entre elles de manière uniforme sans considérer leurs détails – on peut même rajouter de nouvelles classessans modifier l'existant Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 77 |
Chaînage des méthodes Règle générale :éviter les duplications de code – à plus ou moins long terme ca diverge ! ?? code difficile à comprendre ?? difficile à maintenir ?? probablement buggé ! Solutions – utiliser l’héritage ! – le cas échéant, chaînerles méthodes des superclasses!
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 78 | |
Concepts fondamentaux de l’orienté objet En résumé : 4 fondamentaux – 1) méthodes : lien entre les fonctions et les données – 2) encapsulation : crucial en OO (mais possible avec des langages non OO) – 3) héritage : simple ou multiple – 4) polymorphisme d'héritage (dynamique) : toute la puissance de l’OO ! 79 |
Implémentation des méthodes virtuelles
! CarTruck ! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 80 | |||||
Implémentation des méthodes virtuelles
vtable •? chaque objet pointe vers la vtable de sa classe •? vtable = tableau de pointeurs de fonctions 81 |
Implémentation des méthodes virtuelles
0000000100000ff0 t __ZN3Car5startEv 0000000100000f40 t __ZN3CarC1Ei 0000000100000f70 t __ZN3CarC2Ei 00000001000010b0 t __ZN7Vehicle5startEv 0000000100001c70 t __ZN7Vehicle8getColorEv 0000000100000fc0 t __ZN7VehicleC2Ei 0000000100002150 D __ZTI3Car 0000000100002140 D __ZTI7Vehicle U __ZTVN10__cxxabiv117__class_type_infoE U __ZTVN10__cxxabiv120__si_class_type_infoE 0000000100000ec0 T _main! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 82 | ||
Coût des méthodes virtuelles
Coût d'exécution –?double indirection •? coût généralement négligeable –?cas où ca compte : •? méthode appelée très très très souvent ?? plus rapide si non virtuelle ? mais gare aux erreurs si on redéfinit ?la méthode ! 83 |
Coût des méthodes virtuelles
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | Coût mémoire –? un pointeur (vtable) par objet ?? méthodes virtuelles inutiles si : • aucune sous-classe • ou aucune redéfinition de méthode | 84 | ||
Chapitre 3 : Gestion mémoire Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 85 | |||
!
!
! !
Allocation mémoire
Mémoiredynamique(tas/heap) – données créées par new?détruites par delete – la variable pointesurla donnée i! s! Penser à détruire les pointés ! – sinon ils existent jusqu'à la fin du programme – delete ne détruit pas la variable mais le pointé! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 89 | |
Objets et types de base
C++ – traite les objets comme les types de base – idem en C avec les struct – les constructeurs / destructeurs ?sont appelés dans tous les cas Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 90 |
!
!
!
!
!
Opérateurs de copie Interdire le copy constructor et operator= – interdit également la copie des sous-classes – sauf si on redéfinit ces opérateurs pour les sous-classes
| = delete!interdit l'opérateur! 99 |
!
!
!
Coût de l'allocation mémoire
Gratuit ou négligeable – mémoire globale/statique • fait à la compilation – mémoire automatique (pile) • attention : la taille de la pile est limitée ! – objets dans les objets • sous partie du contenant => généralement aucune allocation ! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 102 | ||
Coût de l'allocation mémoire
Gratuit ou négligeable – mémoire globale/statique – mémoire automatique (pile) – objets dans les objets Coûteux – mémoire dynamique(tas) :
• newen C++ et malloc en C • ramasse-miettes en Java – impact important sur les performances • souvent ce qui prend le plus de temps ! • le ramasse-miettes bloque temporairement l'exécution 103 |
Compléments variable globalevariable statique de fichier En C/C++, Java, etc. il y a aussi :! En C/C++ il y a aussi : La mémoire constante (parfois appelée statique) Les variables globales – exple : littéraux comme "Hello Word"! –? accessibles dans toutes les fonctions de tous les fichiers Les variables volatiles => dangereuses ! – empêchent optimisations du compilateur – pour threads ou entrées/sorties selon? Les variables globales statiquesle langage –? accessibles uniquement dans les fonctions d'un fichier Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 104 | ||
Chapitre 4 : Types, constantes et smart pointers Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 105 |
Types de base
| • La taille dépend de laplateforme • char est signé ounonsigné •? entre [0, 255] ou[-128, 127] !! ??attention à laportabilité! • tailles dans <climits> et <cfloat> | |||
! ! | •? Tailles normalisées | |||
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 106 | |||
Typedef et inférence de types typedefcrée un nouveau nom de type typedefShape *ShapePtr;! typedeflist<Shape *>ShapeList;!typedefbool (*compareShapes)(const Shape* s1, const Shape* s2);! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 107 | |||
Typedef et inférence de types typedef crée un nouveau nom de type typedef Shape * ShapePtr;! typedef list<Shape *> ShapeList;! typedef bool (*compareShapes)(const Shape* s1, const Shape* s2);! Inférence de types (C++11) ! autocount = 10;!intcout = 10;!autoPI = 3.1416; ! doublePI = 3.1416 ! ! == ! ShapeListshapes;! list<Shape*>shapes;! autoit = shapes.begin(); ! list<Shape*>::iteratorit = shapes.begin(); decltype (C++11) structPoint{double x, y;};! Point* p =newPoint();!définit le type à partir !decltype(p->x) val = p->x; de celui d'une autre variable! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 108 |
Constantes Macros du C (obsolète) – substitution textuelle avant la compilation #definePORT 3000! #defineHOST"localhost"! Enumérations – pour définir des valeurs intégrales enum{PORT = 3000};! – commencent à 0 par défaut enumStatus {OK, BAD, UNKNOWN};! – existent aussi en Java enum classStatus {OK, BAD, UNKNOWN};! ! Variablesconst – final en Java constint PORT = 3000;! – les littérauxdoivent être const constchar * HOST ="localhost";! constexpr (C++11) constexprint PORT = 3000;! – expression calculée à lacompilation constexpr constchar * HOST ="localhost";! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 109 |
!
!
!
!
Paramètres et méthodes const
Paramètreconst – la fonction ne peut pas modifier ce paramètre Méthodeconst – la fonction ne peut pas modifierl'objet (i.e. ses variables d’instance) Dans les deux cas ?? spécifie ce que la fonction a le droit de faire => évite les erreurs! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 111 |
Copie et const
Qui contrôle quoi ? –? la couleur dépend d'autrui • get :autruipeut la modifier ou la détruire • set : la couleur appartient à autrui(qui peut la modifier ou la détruire) Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 112 | |||
Copie et const
Qui contrôle quoi ? –? à droite : la couleurnedépendpas d'autrui • get : autruinepeut pas la modifier ou la détruire • set : la couleur appartient à l'objet (qui ne doit pas modifier celle d'autrui) Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 113 |
Objets immuables Objets immuables – objets que l'on ne peut pas modifier – peuvent être partagés sans risque, ce qui évite d'avoir à lesdupliquer Deux techniques – l'objet n'a pas de méthode permettantde le modifier – ex : String en Java – variables const – seules les méthodesconst peuvent être appelées
! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 114 | |||
Constance logique
Objet vu comme immuable – l'objet n'a pas de méthode permettant de le modifier : constance logique Mais qui peut modifier son état interne – print() peut allouer une ressource interne : non-constance physique Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 115 |
Smart pointers
shared_ptr(C++11) –?smart pointer avec comptage de références • objet détruit quand le compteur arrive à 0 • => mémoire géréeautomatiquement : plus de delete ! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 116 | |||
Smart pointersShape Circle S'utilisent comme des "raw pointers" – polymorphisme – déréférencement par opérateurs -> ou* comme les raw pointers Attention ! – ne marchent pas si dépendances circulaires entre les pointés ! – ne doivent pointer que sur des objets crées avec new – danger : ne pas les convertir en raw pointers car on perd le compteur ! 117 |
Smart pointers
unique_ptr: si l'objet n'a qu'un seulpointeur – pas de comptage de référence => moins coûteux – utiles pour tableaux ou conteneurs pointant des objets weak_ptr – pointe un objet déjà pointé par un shared_ptr sans le "posséder" – sert à éviter les dépendances circulaires Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 118 | |
Chapitre 5 : Bases des Templates et STL Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 119 |
!
!
!
!
!
!
Exemple passage par const référence! template<typenameT, intL, intC> !(chapitre suivant)!classMatrix{! Tvalues[L*C];!public:! voidset(int i, int j, constT& val) {values[i *C+ j] = val;}! constT&get(int i, int j) const {return values[i *C+ j];}! voidprint() const {! for(int i = 0; i <L; ++i) {! for (int j = 0; j <C; ++j) cout <<get(i,j) <<" ";! cout << endl;! }! }! };! !template<typenameT, intL, intC> ! Matrix<T,L,C>operator+(constMatrix<T,L,C>& a, constMatrix<T,L,C>& b) {! Matrix<T,L,C>res;! for(int i = 0; i <L; ++i)! for(int j = 0; j <C; ++j) ! res.set(i, j, a.get(i,j) + b.get(i,j));! returnres;!NB: on verra une solution plus }!performante au chapitre suivant! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 122 | ||
Standard Template Library (STL)
Conteneurs – pour regrouper et manipuler une collection d'objets – compatibles avec les objets et les types de base – gèrent automatiquement la mémoire nécessaire à leurs éléments •? exples : array, vector, list, map, set, deque, queue, stack Itérateurs – pour pointer sur les éléments : ex : begin() et end() Algorithmes – manipulent les données des conteneurs : ex : reverse() Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 123 |
!
!
!
!
!
!
!
Conteneurs pointant des objets
Cette listepointesur les objets pointés PAS détruits! –?la liste est détruite car path est dans la pile –?mais pas les pointés !! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 127 |
Conteneurs contenantdes objets
OUI Vehicle ! NON CarTruck Problème ?
! 131 |
Conteneurs contenantdes objets
OUI Vehicle ! NON CarTruck
OUI ! Polymorphisme ! –?plusieurs types d'objets (Vehicle, Car, Truck ) => forcement des pointeurs –?en Java on n'a pas le choix : c'est toujours le cas ! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 132 | |||||||||
Deque ("deck")
Deque – mélange de liste et de vecteur : • accès direct aux éléments par [i] ou at(i) • faible coût d'insertion / suppression – mais plus coûteux en mémoire Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 133 |
Enlever des éléments Enlever les éléments à unepositionou unintervalle
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 134 | |||
Enlever des éléments Enlever les éléments ayant une certainevaleur
! ! Enlever les éléments vérifiant unecondition
! ! 135 |
Enlever plusieurs éléments dans une liste
Attention path! – l'itérateur it est invalide après erase()?=> second itérateur it2 Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 136 | ||||||||
Table associative (map) Note •? on pourrait aussi utiliser set 137 | |||||||||
Algorithmes exemple : trier les éléments d’un conteneur
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 138 |
!
!
!
Polymorphisme paramétré Comment avoir une fonctionprint() générique ?
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 140 |
!
!
!
!
!
!
Traits <type_traits>
Informations sur letypeà la compilation : !
! | il n'y a pasis_container!! on va le faire !! | ||||
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 142 | ||||
Traits
! ! On peut détecter lesconteneursà la compilation :
! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 143 |
!
!
!
!
!
Templates C++ vs. Generics Java
Templates C++ – instanciation à la compilation=>optimisationselon les types effectifs –?puissants (Turing complets) mais pas très lisibles ! Generics Java – sémantique et implémentation différentes : • pas de types de base • pas instanciés à la compilation (moins efficaces en CPU mais moins de mémoire) •? pas de spécialisation • pas de traitements sur les types (ils sont « effacés ») Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 145 |
Chapitre 6 : Passage par valeur et par référence Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 146 | ||||
Passer des valeurs à une fonction
Quelle est la relation - entre les arguments (i,s) passés à la méthode print() - et ses paramètres formels (n,p) 147 |
! ! ! ! ! ! ! ! ! !
Récupérer des valeurs d'une fonction
Résultat - 10 YES - 20 NO 153 |
! !
!
!
Récupérer des valeurs d'une fonction
En Java lesréférencesettypes de basesont passées parVALEUR Le passage par référence (ou similaire) existe dans d'autres langages :?C#, Pascal, Ada, etc. Comment faire en Java ? Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 156 |
!
! !
!
!
Références C++ Ce sont des alias : - doivent être initialisées : référencent toujours la même entité - pas de calcul d'adresses dangereux (contrairement aux pointeurs)
C'est l'objet référencé qui est copié :
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 161 |
Chapitre 7 : Compléments Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 162 | ||||
Transtypage vers les superclasses
Object Button Rappel : Correct ? 163 |
!
!
Transtypage vers les sous-classes
Object Button ! Correct ? 165 |
!
!
!
!
!
!
!
!
!
!
!
!
Opérateurs de transtypage
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 169 |
RTTI (typeid)
Retourne de l'information sur le type –? généralement encodé (mangled) Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 170 | |
Types incomplets et handle classes
header Button.h! Handle class : cacher l'implémentation – implémentation cachée dans ButtonImpl •? ButtonImpl déclarée dans header privéButtonImpl.h pas donné au client Références à des objets non déclarés – mousePressed() dépend d'une classe MouseEvent déclarée ailleurs Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 171 |
Types incomplets
header Button.h! Problème – erreur de compilation: ButtonImpl et MouseEvent sont inconnus ! Solution ? Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 172 | ||
Types incomplets
Mauvaise solution – 1) L'implémentation n'est plus cachée : • il faut donner ButtonImpl.h au client ! – 2) Références externes : • if faut inclure plein de headers qui s'incluent les uns dans les autres ! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | header Button.h! | 173 | |
Types incomplets
| header Button.h! | ||
Bonne solution – déclare l'existence d'une classe sans avoir à spécifier son contenu ? (même chose en C avec les struct) – les variables (event,impl) doivent être des pointeurs ou des références Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 174 |
!
!
!
!
!
!
!
!
Pointeurs de fonctions et de méthodes Pointeur de fonction
! ! Limitation des pointeurs de fonctions – fonction non membre : pas d'accès aux objets et à leurs variables •? à moins d'utiliser des variables globales (= BAD ! ) Note – existe en C mais pas en Java |
!
!
!
! !
!
!
!
Foncteurs et lambdas
Limitation des pointeurs ?de méthodes – addCallback() dépend de ?la classe Truc – pratique mais pas générique ! Solutions – templates (voir serveur du TP) – pointeurs de fonctions génériques – foncteurs – lambdas Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 180 | |
Foncteurs Foncteur – l'objet est considéré comme?une fonction – plus besoin de passer l'objet en argument ! – il suffit de définir operator() 181 |
!
!
!
!
!
!
!
!
!
!
Lambdas et capture de variables Lambdas = fonctions anonymes quicapturent les variables • la variable age de foo() est capturée par la lambda • simplifient considérablement le code ! • existent aussi en Java 8, Python
Options • [age] : capture age par valeur (age est copié) • [=] : capture tout par valeur (y compris this dans un objet) • [&] : capture tout par référence (pour modifier les variables) • [] : capture rien
• type de retour implicite par defaut ?sinon écrire : 185 |
Surcharge des opérateurs
Possible pour presque tous les opérateurs = == < > + - * / ++ -- += -= -> () [] new delete mais pas :: . .* ? la priorité est inchangée A utiliser avec discernement – peut rendre le code incompréhensible ! Existe dans divers langages (C#, Python, Ada ) – mais pas en Java Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 186 | |||
Surcharge des opérateurs
operator[] operator() – foncteurs operator-> et operator*
– redéfinissent le déréférencement operator++
Conversion de types Operateurs new , delete , new[], delete[] – changent l'allocation mémoire – exceptionnellement : pour gestion mémoire non standard (exple : embarqué) 187 |
Exemple : smart pointers intrusifs
Principe – la classe de base possède un compteur de références – les smart pointers détectent les affectations et modifient le compteur Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 188 | |||
Exemple : smart pointers intrusifs
! Le smart pointer – encapsule un raw pointer – surcharge le copy constructor, et les operateurs= , -> et * 189 |
Exceptions classMathErr{}; ! !classOverflow: publicMathErr{};! !structZerodivide: publicMathErr{! int x;! Zerodivide(int x) : x(x) {}! };! ! voidfoo() {! try{! int z =calcul(4, 0)! }! catch(Zerodivide& e) { cerr << e.x <<"divisé par 0"<< endl; }! catch(MathErr) { cerr <<"erreur de calcul"<< endl; }! catch( ) { cerr <<"autre erreur"<< endl; }! }! ! intcalcul(int x, int y) {! returndivise(x, y);! }! ! intdivise(int x, int y) {! if (y == 0)throwZerodivide(x); // throw leve l'exception! else return x / y;! }! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 190 | |
Exceptions
But : faciliter le traitement des erreurs - permettent de remonter dans la pile?des appels des fonctions - jusqu'à un point de contrôle Avantage - gestion plus plus centralisée et plus systématique des erreurs •? que des enchaînements de fonctions retournant des codes d'erreurs Inconvénient - peuvent rendre le flux d'exécution difficile à comprendre si on en abuse ! 191 |
Exceptions Différences entre C++ et Java - en C++ on peut renvoyer ce qu'on veut (pas seulement des objets) - en Java les fonctions doivent spécifier les exceptions Spécification d'exceptions de Java
- n'existent pas en C#, obsolètes en C++ - compliquent le code et entraînent des limitations : • en Java une méthode redéfinie dans une sous-classe ?ne peut pas spécifier de nouvelles exceptions Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 192 | |
Exceptions Exceptions standards - exception : classe de base ; header : <exception> - runtime_error - bad_alloc, bad_cast, bad_typeid, bad_exception, out_of_range Handlers - set_terminate() et set_unexpected() spécifient ce qui se passe en dernier recours
Redéclenchement?d'exceptions Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 193 |
Une source d'erreur fréquente
Attention - le pointeur peut être nul ! - ca arrive souvent
Mieux ! - lancer une exception - c'est ce que fait Java
Encore mieux ! - une référence C++ ne peut ?pas être nulle - mais ne pas faire : DANGER : tester que obj n'est pas nul !! 195 |
Une source d'erreur fréquente
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 196 | ||||||||||||
Héritage multiple Principe -? la classe hérite de toutes les variables et méthodes de ses superclasses 197 |
Collisions de noms
Variables ou méthodes ayant le même nom ? NamedRect* p = ;!p->draw(); // ERREUR!! dans les superclasses p->Rect::draw(); // OK! => il faut les préfixer pour pouvoir y accéder p->Name::draw(); // OK! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 198 | |||||
Collisions de noms
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | Solutions • redéfinir les méthodes ?concernées ou • choisir la méthode héritée?avec using | 199 |
Héritage en diamant
Problème • la classe de base (Shape) est dupliquée car elle est héritée des deux côtés • rarement utile ! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 200 | |||
Héritage en diamant
Solution 1 : pas de variables • ne mettre que des méthodes dans les classes de base • c'est ce que fait Java 8 avec les default methods des interfaces 201 |
Héritage virtuel
Solution 2 : héritage sans duplication avecvirtual • un peu plus coûteux en mémoire et en temps • ne pas faire de casts (seulement du dynamic_cast) Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 202 |
Sérialisation But - transformer l'information en mémoire en une représentation externe ?non volatile (et vice-versa) Cas d’usage - persistance : sauvegarde sur / relecture depuis un fichier - transport réseau : communication de données entre programmes Implémentation - Java : en standard mais spécifique à Java - C/C++ : pas en standard (pour les objets) mais extensions : •? Cereal, Boost, Qt, Protocol Buffers (Google), OSC Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 206 |
Sérialisation binaire vs. texte Sérialisation binaire Sérialisation au format texte - objets stockés en binaire -? tout est converti en texte - codage compact mais pas lisible -? prend plus de place mais lisible?par un humain et un peu plus coûteux en CPU - pascompatible d'un ordinateur ? -? compatible entre ordinateurs à l'autre -? formats standards • alignement / taille des nombres • XML/SOAP • little/big endian •? JSON - sauf si format standardisé •? etc. • Protocol Buffers Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 207 |
!
!
!
!
Lecture d’objets (problème) voidread(istream& f)override{! Vehicule::read(f);! f >> power >> model; ! }! ! Problème >> s’arrête au premier espace (‘ ‘, ‘\n’, ’\r’, ’\t’, ’\v’, ’\f’) Solution getline() : lit toute la ligne (ou jusqu'à un certain caractère) voidread(istream& f)override{! Vehicule::read(f);! getline(f, model);! string s;! getline(f, s);! model = stoi(s);! }! ! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 210 | |
Ecrire sur un fichier ! boolsave(conststring&fileName,constvector<Car *>&objects) {! ostreamf(fileName); // f(fileName.c_str()) avant C++11! if (!f) {! cerr<<"Can't open file "<< fileName <<endl;! returnfalse;! }! // seulement avec C++11, sinon utiliser forme usuelle avec begin()/end()! for (autoit:objects) it->write(f); ! returntrue;! }! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 211 |
Lire depuis un fichier boolload(conststring&fileName,vector<Car *>&objects) {! istreamf(fileName);! if (!f) {! cerr<<"Can't open file "<< fileName <<endl;! returnfalse;! }! ! while (f) { // pas d’erreur et pas en fin de fichier! Car* car =newCar();! car->read(f);! if (f.fail()) { // erreur de lecture! cerr<<"Read error in "<< fileName <<endl;! deletecar;! returnfalse;! } ! else objects.push_back(car);! }! returntrue;! }! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 212 |
Classes polymorphes Problème - les objets ne sont pas tous du même type (mais dérivent d’un même type) • e.g. Car, Truck, Bike … => stocker le nom de la classe Principe - en écriture : • 1) écrire le nom de la classe de l’objet • 2) écrire ses attributs - en lecture : • 1) lire le nom de la classe • 2) créer l'objet correspondant • 3) lire ses attributs Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 214 |
Classes polymorphes classVehicle{! public:! virtualconst char*classname() const {return"Vehicle";}! .! };! ! classCar: publicVehicle{! public:! const char*classname() constoverride{return"Car";} ! .! };! ! boolload(conststring& fileName,vector<Vehicle*> & objects);! .! stringclassName;! while (getline(f, className)) {! Vehicle* obj =createVehicle(className); // factory qui sert à! if (obj) obj->read(f); // créer les objets! .! }! .! }! - facon simple de récupérer le nom des classes (voire aussi typeid()) - factory : objet ou fonction qui crée tous les objets Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 215 |
stringstream Flux de caractères -? fonctionne de la même manière que istream et ostream! #include <string>! #include <iostream>! #include <sstream>! !voidfoo(const string& str) {! std::stringstreamss(str);! int power = 0; ! string model;! ss>> power >> model;! cout <<"Vehicle: power:"<< power <<" model: "<< model << endl;! ! Vehicle * obj = new Car();! obj->read(ss);! }! !foo("670 \n Ferrari-599-GTO");! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 216 |
!
!
!
!
Mémoire et sécurité Avec LLVM sous MacOSX 10.7.1 : #include <stdio.h> // en langage C! #include <stdbool.h>! ! #include <string.h>! Enter password: 111111! ! #define CODE_SECRET "1234"! Welcome dear customer ;-)! ! ! int main(int argc, char**argv) ! {! Adresses: ! bool is_valid = false;! 0x7fff5fbff98a 0x7fff5fbff98f char code[5];! ! 0x7fff5fbff998 0x7fff5fbff900! printf("Enter password: ");! scanf("%s", code);! !Débordement de chaînes : if (strcmp(code, CODE_SECRET) == 0) ! is_valid = true;! technique typique de piratage ! if (is_valid) ! informatique printf("Welcome dear customer ;-)\n");! else ! printf("Invalid password !!!\n");! ! printf("Adresses: %p %p %p %p\n",! code, &is_valid, &argc, argv);! ! return 0;! }! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 224 |
!
!
!
Mélanger C et C++ De préférence • tout compiler (y compris les .c) avec compilateur C++ Sion mélange compilation enC et compilation enC++ • édition de liens avec compil C++ • main() doit être dans un fichier C++ • une fonction C doit être déclarée comme suit dans C++ extern "C" void foo(int i, char c, float x);!ou! extern "C" {! void foo(int i, char c, float x);! int goo(char* s, char const* s2);! }! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 226 |
Mélanger C et C++ Dans un header C •? pouvant indifféremment être inclus dans un .c ou un .ccp, écrire : #ifdef __cplusplus! extern "C" {! #endif! ! void foo(int i, char c, float x);! int goo(char* s, char const* s2);! ! #ifdef __cplusplus! }! #endif! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 227 |
Arithmétique des pointeurs Tableaux int tab[10]; tab[k] == *(tab + k) // valeur du kième élément du tableau &tab[k] == tab + k // adresse du kième élément du tableau Pointeurs : même notation ! int* p = tab; // équivaut à : p = &tab[0]; p[k] == *(p + k) // valeur du kième élément à partir de p &p[k] == p + k // adresse du kième élément à partir de p Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 229 |
Manipulation de bits Opérateurs & ET | OU inclusif ^ OU exclusif << décalage à gauche >> décalage à droite ~ complément à un int n = 0xff, m = 0; m = n & 0x10; m = n << 2; /* équivalent à: m = n * 4 */ Attention: ne pas confondre & avec && (et logique) ni | avec | | (ou logique) Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 231 |
Orienté objet en C C C++ typedef struct { classUser{ char* name; char* name; // en fait utiliser string long id; long id; } User; public: User (const char* name, int id); User* createUser (const char* name, int id); virtual ~User( ); void destroyUser (User*); virtual void setName(const char* name); void setUserName (User*, const char* name); virtual void print() const; void printUser (const User*); . . }; void foo() { void foo() { User* u = createUser("Dupont"); User* u = new User("Dupont"); setUserName(u, "Durand"); u->setName("Durand"); .. . destroyUser(u); delete u; u = NULL; u = NULL; Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 232 |
Orienté objet en C typedef struct User {! User* newUser() {! int a;! User* p = (User*) malloc(sizeof(User));! void (*print) (const struct User*);! p->a = 0;! } User;! p->print = printUser;! ! return p;! ! }! typedef struct Player { // subclass! ! User base;! ! int b;! Player* newPlayer() {! } Player;! Player* p = (Player*) malloc(sizeof(Player));! ! p->base.a = 0;! ! p->base.print = printPlayer; // cast nécessaire! void print(const User* u) {! p->b = 0;! (u->print)(u);! return p;! }! }! ! ! ! ! void printUser(const User *u) {! int main() {! printf("printUser a=%d \n", u->a);! Player* p = newPlayer();! }! p->base.a = 1;! ! p->b = 2;! ! print(p);! void printPlayer(const Player *u) {! ! printf("printPlayer a=%d b=%d\n", ! ! u->base.a, u->b);! // NB: en fait il faudrait partager les pointeurs! }! // de fonctions de tous les objets d’une même ! //classe via une vtable! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 233 |
Dans ce cours Organisation du cours – présentation des langages informatique par Patrick Bellot – ce qui est similaire à Java (révision ) – ce qui est différent de Java – interfaces graphiques Java Swing Deux langages support – C++: pour illustrer divers concepts, mécanismes et difficultés présents ?dans les langages courants – Java: pour comparer et pour illustrer la programmation événementielle Liens – – Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 2 | |
1972 : Langage C 1983 : Objective C 1985 : C++ 1991 : Python 1995 : Java 2001: C# 2011: C++11 2014: Swift | Brève historique (très parcellaire) Extension objet du C popularisée par NeXt puis Apple Syntaxe inhabituelle inspirée de Smalltalk Extension object du C par Bjarne Stroustrup aux Bell Labs Vise la simplicité/rapidité d'écriture, créé par G. van Rossum Interprété, typage dynamique Simplification du C++ de SunMicrosystems puis Oracle Egalement inspiré de Smalltalk, ADA A l'origine, le « Java de Microsoft» Egalement inspiré de Delphi, C++, etc. Révision majeure du C++, suivie de C++14 et C++17 Le successeur d'Objective C, par Apple | |
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 3 | |
C++ versus C et Java C++ = extension du langage C – un compilateur C++ peut compiler du C (avec qq restrictions) – un même programme peut combiner C, C++ et Objective C (Apple) ou C# (Windows) C++, Java, C# dérivent de la syntaxe du C – avec l’orienté objet et bien d’autres fonctionnalités Différences notables entre C++ et Java – gestion mémoire, héritage multiple, redéfinition des opérateurs, pointeurs de fonctions et de méthodes, passage des arguments, templates – programmes : • Java : à la fois compilés (byte code) puis interprétés ou compilés à la volée • C/C++ : compilés en code natif (et généralement plus rapides) Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 4 | |
Références et liens Livres, tutoriaux, manuels – Le langage C++, Bjarne Stroustrup (auteur du C++), Pearson – manuel de référence: ou –? faqs, aide: , , etc. – Cours C++ de Christian Casteyde: Liens – Travaux Pratiques de ce cours : – Petit tutoriel de Java à C++ (pas maintenu) : – Toolkit graphique Qt: – Extensions Boost: – Cours C++ de Christian Casteyde: – Site de B. Stroustrup: Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 5 |
Premier chapitre : Des objets et des classes Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 6 | |||||||
Programme C++ Constitué – de classes comme en Java – et, éventuellement, de fonctionsetvariables « non-membre » (= hors classes)?comme en C Bonne pratique : une classe principale par fichier – mais pas de contrainte syntaxique comme en Java
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 7 C/C++ : deux types de fichiers – déclarations dans fichiers header (extension.h ou.hpp – définitions dans fichiers d’implémentation (.cpp) – en général à chaque .h correspond un .cpp En Java Car.h
– tout dans les .java | ou pas d'extension) Truck.h
| ||||||
! |
| |||||||
Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 8 |
! !
!
!
!
!
!
!
! !
!
!
!
!
!
!
Instanciation Dans unautrefichier .cpp :
contient l'adresse ! de l'instance! | |
Instanciation Dans unautrefichier .cpp :
de l'instance! newcrée un objet (= une nouvelle instance de la classe) – 1) alloue la mémoire – 2) appelle le constructeur cest une variable locale qui pointe sur cet objet –? c est un pointeur (d'où l'*) qui contient l’adresse mémoire de l’instance 17 |
Pointeurs C/C++ vs. références Java C++
Javacontient l'adresse ! de l'instance! Pointeur C/C++ – variable qui contient une adresse mémoire – valeur accessible, arithmétique des pointeurs (calcul d'adresses bas niveau) Référence Java – variable qui contient l'adresse mémoire d'un objet (ou mécanisme équivalent) – valeur cachée, pas d'arithmétique | |||
Pointeurs C/C++ vs. références Java C++
Javacontient l'adresse ! de l'instance!
Il n'y a pas de "magie", c'est à peu près la même chose (à part qu'il y a un ramasse-miettes en Java) 19 |
Accès aux variables et méthodes d'instance
L'opérateur->déréférence le pointeur – comme en C – mais . en Java Les méthodes d'instance – ont automatiquement accès aux variables d’instance Problème ? – sont toujoursappliquées à un objet | ||||
Encapsulation
Problème –? radius est private => c n’a pas le droit d’y accéder 21 |
Encapsulation
Encapsulation – séparer la spécification de l'implémentation (concept de "boîte noire") – spécification: déclaration des méthodes • interface avec l’extérieur (API) => on ne peut interagir que via les méthodes – implémentation: variables et définition des méthodes • interne à l’objet => seul l'objet peut accéder à ses variables |
Destruction des objets
deletedétruit l'objetpointépar le pointeur (pas le pointeur !) – 1) appelle le destructeur (s'il y en a un) – 2) libère la mémoire Rappel: pas deramasse miettesen C/C++ ! – sans delete l'objet continue d'exister jusqu’à la fin du programme – une solution : smart pointers (à suivre) 27 |
Destructeur / finaliseur
Methode appeléeAVANT?la destruction de l'objet Ne détruit pas l'objet ! – c'est delete qui le fait En C++ – méthode ~Circle() – les destructeurs sont chaînés (chaînage ascendant) En Java – méthode finalize() – les finaliseurs ne sont pas chaînés (et rarement utilisés) | |
Destructeur / finaliseur
Sert à "faire le ménage" – fermer un fichier, une socket – détruire d'autres objets : ?ex: objet auxiliaire créé dans le constructeur En général il n'y en a pas ! – exple: ~Circle() ne sert à rien ! – note : les classes de basepolymorphes doivent avoir un destructeurvirtuel (à suivre) 29 |
Pointeurs nuls vs. pendants voidfoo(Circle* c) {! unsigned int area = 0;! if (c)area = c->getArea(); ! elseperror("Null pointer");! }! ! voidbar() {! Circle* c = newCircle(10, 20, 30);! foo(c);! deletec; // l'objet est détruit => c estpendant! c =nullptr; // c pointe surrien: OK!!foo(c); // OK car c est nulsinon plantage !! deletec; // OK car c est nul! }! Pointeur pendant =invalide ! – pointe sur un objet qui n'existe plus Pointeur nul = pointe sur rien – nullptr en C++ (autrefois:NULLou0) / null en Java | ||||
Pointeurs nuls vs. pendants
deletec; // c estpendant = DANGER !!!! c =nullptr; // c pointe surrien=OK!! Pointeur pendant =invalide ! – pointe sur un objet qui n'existe plus Pointeur nul = pointe sur rien – nullptr en C++ (autrefois:NULLou0) / null en Java 31 |
!
!
!
!
!
!
!
!
!
!
!
Surcharge (overloading)
Fonctions ou méthodes – ayant le même nom mais des signatures différentes – pareil en Java Attention : méthodes d'unemêmeclasse ! – ne pas confondre avec laredéfinition de méthodes (overriding) ?dans une hiérarchie de classes Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 34 | ||
Paramètres par défaut
! Alternative à la surcharge – n'existe pas en Java – les valeurs par défaut doivent être à partir de la fin –? erreur de compilation s'il y a des ambiguïtés
! 35 |
!
Namespaces
! !
namespace= espace de nommage – évitent les collisions de noms – similaires aux package de Java, existent aussi en C# Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 39 |
! !
Streams: entrées / sorties standard
Flux standards std = namespace de la bibliothèque standardstd::coutconsole out= sortie standard std::cerrconsole erreurs= sortie des erreurs (non bufferisées : affichage immédiat) std::cinconsole in= entrée standard 41 |
!
!
!
classCircle{! private:! int x, y; ! unsigned int radius;! public:! Circle(int x, int y, unsigned int radius);! voidsetRadius(unsigned int); ! unsigned intgetRadius() const;! unsigned intgetArea() const;! .! }; |
Toujours appliquées à un objet :
voidfoo() {!
Circle* c = newCircle(100, 200, 35);! unsigned int r = c->getRadius();!
unsigned int a =getArea(); // problème !!!!
}!
!
!
Mais pas la pourquoi ?!
!unsigned intgetArea() const {!
return PI *getRadius()*getRadius();!
}!
!
Comment la méthode accède à radius ?!
!unsigned intgetRadius() const { ! returnradius; !
}!
45
! !
! !
! !
!
Documentation
Doxygen: documentation automatique – similaire à JavaDoc mais plus général (fonctionne avec de nombreux langages) – documentation : Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 47 |
Style et commentaires Règles • être cohérent • indenter (utiliser un IDE qui le fait automatiquement : TAB ou Ctrl-I en général) • aérer et passer à la ligne (éviter plus de 80 colonnes) • camelCase et mettre le nom des variables (pour la doc) • commenter quand c'est utile | ||
Chapitre 2 : Héritage et polymorphisme Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 49 |
Héritage 2eConcept fondamental de l’OO Classe A
– les sous-classes héritentles méthodes et variables ?de leurs super-classes : • la classe B a une méthode foo() et une variablex – héritage simple • une classe ne peut hériter que d'une superclasse Classe B
– héritage multiple • une classe peut hériter de plusieurs classes • C++, Python, Eiffel, Java 8 – entre les deux • héritage multiple des interfaces • Java, C#, Objective C |
!
!
!
ExempleRect classRect{! protected: ! int x, y;! unsigned int width, height;!
Squarepublic:! Rect();! Rect(int x, int y, unsigned int w, unsigned int h);! ! unsigned intgetWidth() const;! unsigned intgetHeight() const;! virtualvoidsetWidth(unsigned int w){width = w;}!virtualvoidsetHeight(unsigned int h){height = h;}! // etc ! };! !classSquare: publicRect{ ! public: ! Square();! Square(int x, int y, unsigned int size);! ! voidsetWidth(unsigned int w)override{width = height = w;}! sinon ce n'est! voidsetHeight(unsigned int h)override{width = height = h;}! plus un carré ! ! };! |
!
!
!
Remarques Chaînage des constructeurs Square::Square() :Rect() {}! chaînage explicite du constr. de la superclasse ! Square::Square() {}! chaînage implicite : fait la même chose ! Square::Square(int x, int y, unsigned int w) ! : Rect(x, y, w, w) { }! même chose que super()de Java
Covariance des types de retour – redéfinition de méthode => même signature – mais Muche peut-être une sous-classe de Truc | |||||||
Classes de base
Shape.h
Circle.hRect.h
Erreur de compilation : Quel est le problème ? Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 57 |
! !
!
!
!
! !
! !
!
!
Directives du préprocesseur Header !inclut ce qui suit jusqu'à#endif! Truc.h! seulementsiTrucn'est pas déjà défini! définitTruc! -? doit êtreunique! Directives de compilation – #if/#ifdef/#ifndefpour compilation conditionnelle – #import(au lieu de #include) empêche l'inclusion multiple (mais pas standard) Headers – #include"Circle.h"cherche dans le répertoirecourant – #include<iostream>cherche dans les répertoiressystèmes (/usr/include, etc.) ?et dans ceux spécifiés par l'option -I du compilateur : gcc –Wall-I/usr/X11R6/include–o myprog! ! Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 60 | ||
Polymorphisme d'héritage Rect
3econcept fondamentalde l’orienté objet – le plus puissant mais pas toujours le mieux compris ! Un objet peut être vu sous plusieurs formes
– un Square est aussi un Rect Square – mais l'inverse n'est pas vrai ! #include"Rect.h"! !voidfoo() {! Square* s = newSquare(); // s voit l'objet comme unSquare! Rect* r = s; // r voit objet comme unRect(upcastingimplicite)! ! Square* s2 = newRect(); // OK ?! Square* s3 = r; // OK ?! }! 61 | |||
Buts du polymorphisme Rect
Pouvoir choisir le point de vue le plus approprié ?selon les besoins Pouvoir traiter un ensemble de classes liées entre elles ?
#include"Rect.h"! !voidfoo() {! Square* s = newSquare(); // s voit l'objet comme unSquare! Rect* r = s; // r voit objet comme unRect(upcastingimplicite)! ! Square* s2 = newRect(); // erreur de compilation!(downcastinginterdit !)! Square* s3 = r; // erreur de compilation!! }! |
!
Polymorphisme : Java Rect
Question à $1000 – quelle méthode setWidth() est appelée :?celle du pointeur ou celle du pointé ?
Rect* r = newSquare();! Squarer->setWidth(100);! ! Java – liaisondynamique /tardive : choix de la méthode à l'exécution ?? appelle toujours la méthode dupointé •? heureusement sinon le carré deviendrait un rectangle ! |
!
!
!
Règles à suivreShape Remarques • une redéfinition de méthode virtuelle ?est automatiquement virtuelle • une classe peut être finalRect
• attention :même signature ?sinon c'est de la surcharge ! Square
67 |
Règles à suivreShape Méthodes non virtuelles : dans quel cas ? • classepas héritée • méthodejamais redéfinie –?typiquement : getters et setters Rect
• méthode qu'on l'appelle très très très souvent : • appel un peu plus rapide –?généralement négligeable! –?gare aux erreurs !
Dans le doute on peut mettreSquarevirtualpartout et optimiser plus tard ! | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Méthodes et classes abstraites
Méthodeabstraite – spécification d'un concept dont la réalisation diffère selon les sous-classes • pas implémentée • doit êtreredéfinieetimplémentée dans les sous-classes instanciables Classeabstraite – classe dont au moins une méthode est abstraite Java – pareil mais mot clé abstract Eric Lecolinet - Télécom ParisTech - Programmation orientée objet et autres concepts illustrés en C++11 | 69 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Bénéfices des classes abstraites
Méthodeabstraite –? spécification d'un concept dont la réalisation diffère selon les sous-classes • pas implémentée • doit être redéfinie et implémentée dans les sous-classes instantiables
! ! ! ! ! ! !
! ! ! !
! ! ! ! !
! ! !
! ! ! !
! ! ! ! ! !
! ! ! ! ! ! !
|