La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Concepts orientés objets

Présentations similaires


Présentation au sujet: "Concepts orientés objets"— Transcription de la présentation:

1 Concepts orientés objets
Programme de baccalauréat en informatique Programmation Orientée Objets IFT-19946 Thierry EUDE Module 2 : Concepts orientés objets Département d’informatique et de génie logiciel

2 Département d'informatique - Université Laval
22/04/2017 2. Concepts orientés objets 2.1 Introduction Département d'informatique - Université Laval H2007

3 Un objet Un objet possède 2 types de propriétés :
Statiques : état, attributs. Dynamiques : comportements, services. Exemple : le chat de ma voisine Statiques : son nom (Phillipon) son poids (18 livres – je sais il est gros...) sa couleur (noir et blanc) Dynamiques : il miaule quand il a faim il se couche sur son cousin près du sofa il mange des mouches

4 Une classe Phillipon est un digne représentant de la race des chats.
Phillipon est une instance de la classe des chats. Tous les chats ont des propriétés communes : ils miaulent (propriété dynamique) ils ont une moustache (propriété statique) etc. Chat : classe représentant un ensemble d’objets ayant : des attributs semblables des comportements semblables.

5 Vers une hiérarchie de classes
Si on poursuit l’analogie, il existe : Différents, mais partagent tous des caractéristiques : ils mangent de la viande leurs griffes peuvent se rétracter leurs molaires sont coupantes ils ont une moustache

6 Vers une hiérarchie de classes
Généralisation: races chat, lion et tigre => super-race nommée félins. La super-race définit : des propriétés des comportements valides autant pour les chats que pour lions et tigres. En termes informatiques, la classe Félin correspond à une super-classe des classes Chat, Lion et Tigre. Chat, lion, tigre : classes dérivées de la classe Félin héritent des propriétés et des comportements de leur super-classe. C’est le concept d’héritage.

7 Vers une hiérarchie de classes
Extension du concept d’héritage : arbre d’héritage. On s’attend à certaines caractéristiques de Phillipon Il est une instance (objet) de la classe Chat ( miauler, dormir, moustaches). On s’attend à ce qu’il puisse se mouvoir non pas parce qu’il est un chat, mais parce qu’il appartient à la classe Animal, donc par héritage.

8 Polymorphisme Les chats, les serpents et les poissons partagent tous un comportement commun hérité de la classe des animaux : ils ont la capacité de se mouvoir. Tous le font, mais chacun à sa manière : le chat marche le serpent rampe le poisson nage Si on donne l’ordre de se mouvoir, chaque animal va pouvoir répondre à cet ordre, à sa manière propre. polymorphisme

9 Encapsulation Phillipon miaule, marche, mange :
Nous connaissons les manifestations extérieures du miaulement, mais la façon dont le son est produit nous est masqué. Chat = abstraction On ne montre seulement que quelques comportements. Une interface représente cette abstraction. Énonce les services offerts Les détails de fonctionnement sont cachés. Emphase sur la compréhension des éléments importants, sans se soucier de l’implantation.

10 Synthèse 1 2 3 4 5

11 Département d'informatique - Université Laval
22/04/2017 2. Concepts orientés objets 2.1 Introduction 2.2 LE MODÈLE OBJET Département d'informatique - Université Laval H2007

12 Les composantes de l’objet
Un objet a : un état, un comportement une identité unique. La structure et le comportement d'objets semblables sont définis dans la classe qui leur est commune. Les termes instance, occurrence et objet sont synonymes.

13 Les composantes de l’objet
État de l'objet : Valeurs de ses attributs ou de l'information qu'il contient. Comportement de l'objet Ensemble des opérations que l'on peut effectuer sur celui-ci. Identité de l'objet Deux objets peuvent être exactement dans le même état, mais sont différents de part leur identité unique ex.: adresse en mémoire.

14 Éléments de définitions de l’objet
“Chose” tangible et/ou visible “Chose” que l'on peut concevoir intellectuellement Rôles (ex. : mère, professeur, politicien) Interfaces usagers et matériel du système Événements et transactions Personnes et emplacements Classes de fondement: chaîne, vecteur, liste chaînée, dictionnaire, date... Organisations

15 La classe ? Objet = entité discrète qui existe dans le temps
et dans l'espace. Classe = abstraction qui n’existe que dans les programmes. doit représenter un ensemble d'objets qui partagent une structure commune et un comportement commun. définit les opérations permises sur les objets de la classe. les états qu’ils peuvent prendre (transitions d’états).

16 Un objet doit être valide de sa création jusqu’à sa destruction.
La classe et ses objets La classe responsable d’assurer la validité de tous les objets créés à partir d’elle-même. Un objet doit être valide de sa création jusqu’à sa destruction. ne pas permettre l’accès direct aux attributs! La théorie du contrat pourrait gérer cette validité (nous y reviendrons).

17 Interface et implémentation
L'interface d'une classe définit ce qui est vu de l'extérieur. renforce la notion d'abstraction en ne montrant que ce qui est nécessaire. contient principalement les déclarations de toutes les opérations applicables sur les instances de cette classe. L'implémentation d'une classe est ce qui est caché à l'intérieur, principalement le code réalisant les opérations définies dans l'interface.

18 Interface d’une classe : exemple
class Pile { public: Pile (int capacite); ~Pile (); int pop (); void push (int); int top () const; void init (); private: ... };

19 Synthèse Objet Classe Interface

20 Département d'informatique - Université Laval
2. Concepts orientés objets 2.1 Introduction 2.2 Modèle objet 2.3 La classe Département d'informatique - Université Laval

21 Problèmes avec une structure
Structure vs Classe Problèmes avec une structure Exemple : Date struct Date { int m_jour; int m_mois; int m_annee; }; Date = nouveau type. Variables déclarées à l'intérieur de la structure  attributs Il est possible d'accéder directement aux attributs.

22 Exemple avec une structure
struct Date { int m_jour; int m_mois; int m_annee; }; void main() { Date uneDate; // --- date valide uneDate.m_jour = 30; uneDate.m_mois = 3; uneDate.m_annee = 1965; // --- date invalide uneDate.m_mois = 2; }

23 Problème avec une structure
Accès aux attributs non contrôlée par la structure. Possibilité de non-initialisation. Possibilité de mauvaise assignation. Pas de garantie sur la validité des données. Si changement de l'implantation de Date … Exemple : On veut conserver un entier correspondant au nombre de secondes écoulées depuis un moment précis, … revoir l'utilisation de la structure un peu partout dans le code.

24 Implémentation d’une classe : les étapes
Déclarer les attributs dans la section privée de la définition de la classe. Déclarer les méthodes dans la section publique de la définition de la classe. Définir l’implantation des méthodes après la définition de la classe dans un fichier séparé (pour le C++). Utiliser la classe en créant des objets de ce type dans un programme.

25 Déclarer les attributs
État d’un objet : décrit par ses attributs: class Date { // ... private: int m_jour; int m_mois; int m_annee; }; Attributs déclarés privés On ne peut y accéder directement.

26 Accès direct impossible !!! Les attributs sont déclarés privés.
Exemple : classe Date class Date { private: int m_jour; int m_mois; int m_annee; }; main() { Date uneDate; uneDate.m_jour = 30; uneDate.m_mois = 3; uneDate.m_annee = 1965; } Accès direct impossible !!! Les attributs sont déclarés privés.

27 Déclarer puis implanter les méthodes
Rôle des méthodes de la classe : La classe Date n’accepte pour valeur qu’un sous-ensemble des valeurs possibles. contrôler l’assignation des valeurs sur les champs. Exemple: 31/02/1965 n’est pas une date valide.

28 Fonctions vs méthodes Nous parlons ici de programmation orientée objet. struct Date { int m_jour; int m_mois; int m_annee; }; void initialise(Date& date, int jour, int mois, int annee); class Date { public: void initialise(int jour, int mois, int annee); private: int m_jour; int m_mois; int m_annee; };

29 Fonctions vs méthodes Fonction, exemple :
void initialise(Date& date, int jour, int mois, int annee) { date.m_jour = jour; date.m_mois = mois; date.m_annee = annee; } La fonction doit avoir les valeurs à assigner ET la date sur laquelle travailler. main() { Date uneDate; initialise(uneDate, 30, 3, 1965); } La date sur laquelle travailler.

30 Fonctions vs méthodes Méthode, exemple :
void Date::initialise(int jour, int mois, int annee) { m_jour = jour; m_mois = mois; m_annee = annee; } Accès direct aux attributs de l'objet courant. main() { Date uneDate; uneDate.initialise(30, 3, 1965); } L'objet sur lequel appliquer l'initialisation.

31 Fonctions vs méthodes Les différences :
void initialise(Date& date, int jour, int mois, int annee) { date.m_jour = jour; date.m_mois = mois; date.m_annee = annee; } La fonction est globale. Accès direct aux attributs de la structure. void Date::initialise(int jour, int mois, int annee) { m_jour = jour; m_mois = mois; m_annee = annee; } La méthode a une portée limitée à la classe Date. Accès direct aux attributs de l'objet courant.

32 void Date::initialise(int j, int m, int a)
Objet courant On peut référer à l'objet courant explicitement en général ce n'est pas de mise. En C++, this permet de référer au pointeur à l'objet courant. void Date::initialise(int j, int m, int a) { this->m_jour = j; this->m_mois = m; this->m_annee = a; }

33 … visibilité par défaut
Structure et Classe Différence entre une structure et une classe en C++ ? … struct Date { int m_jour; int m_mois; int m_annee; }; class Date { int m_jour; int m_mois; int m_annee; }; … visibilité par défaut Structure : visibilité publique. Classe : visibilité privée.

34 Structure et Classe: différences?
La classe peut avoir des méthodes et des attributs avec la visibilité explicite : public, private… Norme : Toujours spécifier la visibilité explicitement.

35 Synthèse Structure - 1 2 Classe

36 Initialisation création d'un objet, constructeur.
ses attributs doivent être initialisés pour que celui-ci soit dans un état cohérent. constructeur. constructeur = méthode spéciale. a le même nom que la classe. est automatiquement appelé à la création d'un objet de la classe. méthode qui n'a pas de type de retour ne retourne pas de valeur.

37 Par contre, on peut faire :
Les constructeurs Protection des attributs : Date d; d.m_jour = 31; d.m_mois = 3; d.m_annee = 1965; Impossible ! Par contre, on peut faire : Date d; d.initialise(31,3,1965); Problème : pendant un certain temps l'objet Date n'est pas correctement initialisé. Solution: utiliser la méthode spéciale qu'est le constructeur

38 Les constructeurs class Date { public: Date(int jour, int mois, int annee); ... }; Date::Date(int jour, int mois, int annee) m_jour = jour; m_mois = mois; m_annee = annee; } Constructeur automatiquement appelé lorsqu’un objet Date est déclaré: Date d(1, 1, 1997); Par contre, on ne peut plus écrire: Date d;

39 Les constructeurs Il est possible d’avoir plusieurs constructeurs dans une même classe. Caractéristique du langage : Plusieurs méthodes du même nom = surcharge de méthode. Lorsqu'une fonction surchargée est appelée, le compilateur sélectionne la bonne fonction selon les arguments: nombre, type, ordre..

40 Les constructeurs On peut vouloir en même temps :
un constructeur qui accepte la date complète un constructeur par défaut constructeur auquel on ne fournit pas de donnée. Exemple : class Date { public: Date(); Date(int jour, int mois, int annee); };

41 Les constructeurs Mais aussi que :
Le constructeur par défaut de la classe Date puisse prendre la date courante du système en guise de date. Un constructeur permettant d’initialiser une date à partir d’une chaîne de caractères d’un format déterminé: Date(const std::string& txtDate);

42 Les constructeurs : exemple
class Date { public: Date(); Date(int jour, int mois, int annee); Date(const std::string& txtDate); }; Constructeurs dans l’ordre Date e; Date d(31,3,1997); Date f("31 mars 1997"); Date g(31, "mars", 1997); Date vDate[10]; Date(int,string,int); n’existe pas! Date() appelé 10 fois

43 Construction des sous-objets
Utilisez une liste d’initialisation: construire tous les sous-objets avant le corps du constructeur parce que lorsqu'on y est rendu, ces objets sont déjà construit, i.e. on a déjà appelé leur constructeur par défaut. Date::Date(int jour, int mois, int annee) { // Les attributs ont déjà été initialisés par défaut. m_jour = jour; m_mois = mois; m_annee = annee; } // Version préférable Date::Date(int jour, int mois, int annee) : m_jour(jour), m_mois(mois), m_annee(annee) { } Liste d'initialisation

44 Construction des sous-objets
Exemple 2 : Message::Message(const string& expediteur, const string& destinataire, const Date& dateRecu, const string& titre, const string& message) : m_expediteur(expediteur), m_destinataire(destinataire), m_dateRecu(dateRecu), m_titre(titre), m_message(message) { } Construire un objet avec des valeurs par défaut pour ensuite les changer avec les valeurs désirées. Un appel de plus est fait inutilement.

45 Le destructeur méthode particulière de la classe.
porte le même nom que la classe mais précédé par un tilde ~. est exactement le complément du constructeur Le constructeur initialise les attributs et alloue des ressources s’il y a lieu, le destructeur libère les ressources si nécessaire. Ne détruit pas l'objet: il fait le ménage à l’intérieur avant la destruction.

46 Le destructeur Ne reçoit pas de paramètre et ne retourne pas de valeur. Un seul par classe. Facultatif: Le compilateur en génère un qui ne fait rien. Est utile lorsque l’objet est responsable de ressources allouées dynamiquement. Ne pas implanter de destructeur s'il n'y a pas de désallocation de ressource.

47 Constructeur / Destructeur
class Date { public: Date(int j, int m, int a); ~Date(); private: int m_jour; int m_mois; int m_annee; }; Date::Date(int j, int m, int a) : m_jour(j), m_mois(m), m_annee(a) } Date::~Date() Date déclarée Constructeur appelé void main() { Date d(1, 1, 1965); } Initialisation seulement Sortie du «scope», destructeur appelé Rien à faire? => ne pas implanter

48 Constructeur / Destructeur
string déclarée, constructeur appelé class string { public: string(const char* strP); ~string(); private: char *m_strP; }; string::string (const char* strP) m_strP = new char[strlen(strP)+1]; strcpy (m_strP, strP); } string::~string() delete [] m_strP; void main() { string s("Bonjour"); } Sortie du «scope», destructeur appelé Initialisation et allocation de ressources. Désallocation de ressources

49 Synthèse Constructeur : Destructeur :

50 2.4 Méthodes par catégorie
2. Concepts orientés objets 2.1 Introduction 2.2 Élément du modèle objet 2.3 La classe 2.4 Méthodes par catégorie Département d'informatique - Université Laval

51 Méthodes par catégorie
Accès Assignation Comparaison Utilitaires Statiques Optimisées

52 Méthode d’accès class Date { public: ... int reqJour () const;
int reqMois () const; int reqAnnee () const; }; Accéder à l’information sans modifier  méthodes constantes.

53 Méthodes constantes : protection des données
méthodes d’accès en lecture vs méthodes qui modifient l’état de l’objet. traitement spécial on doit les déclarer constantes. En C++, mot clé : const Indique l'intention de ne pas modifier l’objet dans cette méthode

54 Méthodes constantes : exemple
class Date { public: ... int reqJour () const; int reqMois () const; int reqAnnee () const; }; Le mot-clé const se retrouve dans l’interface et dans l’implantation int Date::reqJour () const { return m_jour; } Le compilateur fera la vérification que les attributs de l’objet ne seront pas modifiés dans cette méthode.

55 Méthodes constantes Outil permettant d’améliorer la qualité du code de façon très importante il force la classification. Il faut adhérer à cette façon de faire si on désire partager du code et utiliser des librairies qui ont adhéré à cette norme. La librairie standard adhère à cette norme.

56 Méthodes constantes : exemple
class Date { public: void imprime(); private: int m_jour; int m_mois; int m_annee; }; void Date::imprime() { cout << m_jour << ":" << m_mois << ":" << m_annee; } Ne compile pas! le compilateur ne peut deviner que vous ne modifiez pas la date en l’imprimant... class Message { public: void imprime() const; private: string m_expediteur; Date m_dateRecu; }; void Message::imprime() const { cout << m_expediteur << endl << m_dateRecu.imprime(); }

57 Méthodes d’assignation
Accès Méthodes d’assignation class Date { public: void asgJour (int jour); void asgMois (int mois); void asgAnnee (int annee); private: int m_jour; int m_mois; int m_annee; }; void Date::asgJour(int jour) { m_jour = jour; } void Date::asgMois(int mois) m_mois = mois; void Date::asgAnnee(int annee) m_annee = annee; objet dans un état incohérent. asgDate(int jour,int mois,int annee); préférable!  contrôle des changements sur les attributs de la date sans jamais avoir d'état intermédiaire invalide.

58 Méthode d’assignation : exemple
class Date { public: void asgDate(int j, int m, int a); private: int m_jour; int m_mois; int m_annee; }; void Date::asgDate(int j, int m, int a) { m_jour = j; m_mois = m; m_annee = a; } On pourra vérifier la validité du format des données

59 Méthode de comparaison
Accès Assignation Méthode de comparaison Implantation d'un nouveau type Nécessité de pouvoir comparer celui-ci par rapport à un objet du même type. Exemple : une Date comparée à une autre Date: Est-elle égale ? Est-elle inférieure ? Ce type de méthode retourne un booléen.

60 Méthode de comparaison
class Date { public: bool estEgal(const Date& d) const; private: int m_jour; int m_mois; int m_annee; }; bool Date::estEgal(const Date& d) const { return m_jour == d.m_jour && m_mois == d.m_mois && m_annee == d.m_annee; } Évaluation de l'égalité sur la base de la valeur des attributs de l'objet courant par rapport à l'objet passé en paramètre. void main() { Date d1(4,9,2002); Date d2; if (d2.estEgal(d1)) }

61 Synthèse

62 Méthodes utilitaires Rappel: en général, toutes les méthodes publiques
Accès Assignation Comparaison Méthodes utilitaires Rappel: en général, toutes les méthodes publiques tous les attributs privés. Méthodes utilitaires : à l’intérieur de la classe sans pour autant vouloir en faire un service publique. sont appelées par les autres méthodes de la classe.

63 Méthode utilitaire : exemple
class Date { public: ... std::string reqDateFormatee() const; private: std::string reqNomMois() const; }; Date d(2,5,1994); cout << d.reqDateFormatee() << endl; Résultat : 2 mai 1994 std::string Date::reqDateFormatee () const { ostringstream os; os << reqJour() << " " << reqNomMois() << " " << reqAnnee(); return os.str(); } Méthode utilitaire utilisée à l'intérieur de la classe std::string Date::reqNomMois () const { static char* NomMois[] = {"janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre","novembre", "décembre"}; return NomMois[reqMois()]; }

64 Accès Assignation Comparaison Utilitaires Méthodes statiques Méthode de classe ne nécessitant pas la présence d'un objet pour le traitement méthode statique. Comme une fonction mais associée à la classe. Ne touche pas aux attributs de la classe, à moins que ceux-ci ne soient aussi statiques (attribut commun à tous les objets de la classe).

65 Méthodes statiques : exemple
Pas de const pour une méthode statique --- INTERFACE --- class Date { public: void asgDate (int jour, int mois, int annee); static bool valideDate (int jour, int mois, int annee); static bool estBissextile (int annee); private: }; --- IMPLÉMENTATION --- int Date::jourParMois[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; bool Date::valideDate(int jour, int mois, int annee) { return jour > 0 && mois > 0 && mois <= 12 && ((mois == 2 && jour == 29 && Date::estBissextile(annee)) || (j < jourParMois[mois - 1])); } bool Date::estBissextile(int annee) return (((annee % 4 == 0) && (annee % 100 != 0)) || ((annee % 4 == 0) && (annee % 100 == 0) && (annee % 400 == 0)) ); La méthode peut être déclarée Statique puisque aucun attribut non statique n'est utilisé

66 N'a pas besoin d'un objet du type de la classe pour être appelée.
Méthodes statiques N'a pas besoin d'un objet du type de la classe pour être appelée. Norme : Toujours appeler les méthodes statiques avec le «scope» de la classe et ce, même si vous avez un objet de ce type entre les mains. void main() { if (Date::valideDate(30,2,1999)) if (Date::estBissextile(2000)) }

67 Méthode et attribut statiques : exemple
class Etudiant { public: Etudiant () {m_nbInstances++;} ~Etudiant () {m_nbInstances--;} static int reqNbInstances () {return m_nbInstances;} private: static int m_nbInstances; }; int Etudiant::m_nbInstances=0; void main() Etudiant et1, et2, et3; cout << "Résultat :" << endl; cout << Etudiant::reqNbInstances() << endl; Etudiant et4, et5; } On peut utiliser un attribut statique dans un objet Une méthode statique ne peut qu'utiliser des attributs statiques. Attribut commun à tous les objets de la classe Résultat: 3 5 On sort du "scope": appel au destructeur

68 Méthodes optimisées Accès aux attributs :
Assignation Comparaison Utilitaires Statiques Méthodes optimisées Accès aux attributs : toujours passer par des méthodes. Méthodes qui transmettent simplement la valeur d’un attribut ... Pénalisant! Faire un appel de fonction veut dire: mettre sur la pile d’appel l’adresse de retour ainsi que les paramètres d’appel. branchement vers le code exécutable de la fonction. Retour : dépiler l’adresse de retour récupérer les résultats...

69 Méthodes optimisées Solution en C++ pour les méthodes simples:
les déclarer inline. = Le compilateur élimine l’appel de fonction en le remplaçant par un accès direct à la donnée. Le code de la méthode doit être très simple et ne pas avoir d’effet de bord. Les méthodes inline font croître rapidement la dimension du code exécutable...

70 Méthodes optimisées : exemple
class Date { public: void asgDate(int jour,int mois,int annee); int reqMois() const; }; inline int Date::reqMois() const return m_mois; } Date.h Méthode inline Méthode non inline #include "Date.h" void Date::asgDate(int jour, int mois, int annee) { m_jour = jour; m_mois = mois; m_annee = annee; } Date.cpp

71 Fonction inline ou macro?
Les programmeurs en C font souvent usage du préprocesseur avec #define pour implanter un fonction inline : #define carre(x) (x)*(x); int x = 5; int y = carre(++x); Résultat : 49 !??! inline int carre(int x) {return x*x;} int x = 5; int y = carre(++x); Résultat : 36.

72 Fonction inline ou macro
L'usage de remplacement de symboles avec #define est source d'erreur, notamment pour les fonctions mathématiques. En C++, utiliser les fonctions ou les méthodes inline à la place. Les méthodes inline assurent la protection des données (encapsulation) assurent la validation de type d'une fonction régulière. améliorent la performance en évitant les appels de fonction.

73 Synthèse

74 Département d'informatique - Université Laval
2. Concepts orientés objets 2.1 Introduction 2.2 Élément du modèle objet 2.3 La classe 2.4 Méthodes par catégorie Département d'informatique - Université Laval 2.5 Implantation avancée

75 Implantation avancée Problème de collision de noms Entrées/sorties Le passage de paramètres Surcharge de méthode

76 Problème de collision de noms…
Qu’arrive-t-il si 2 fonctions globales différentes ont le même prototype ? // MaLib2.h int f(); class A{}; // MaLib1.h int f(); #include "MaLib1.h" #include "MaLib2.h" int g(){ return 5 + f(); //Quel f() ? }

77 Solution : créer de namespaces
regroupement logique de fonctions, de classes, etc. Possibilité de lui donner un nom. - NomDuNamespace::NomDeLEntite Pas d'ambiguïté

78 exemple // MaLib1.h // MaLib2.h namespace Util{ namespace Tp1{
int f(); } // MaLib2.h namespace Tp1{ int f(); class A{}; } #include "MaLib1.h" #include "MaLib2.h" int g(){ Tp1::A a; return 5 + Util::f(); // Ah, ok } On se sert de l'opérateur d'appartenance ::

79 using namespace namespace directement accessible : commande using
22/04/2017 using namespace namespace directement accessible : commande using #include "MaLib1.h" #include "MaLib2.h" using namespace Tp1; int h(){ A a; int x = f(); return x + Util::f(); } Par le using, c'est Tp1::f(). H2007

80 Bon usage du using Inutile de mettre des using pour chacun des namespaces disponibles : l'ambiguïté revient. Un using peut-être local : Ne jamais utiliser de using dans un .h : tous les fichiers qui l'incluront seront pollués. // Quelque part { using namespace Util; // Util est accessible directement dans ce bloc }

81 Namespace et librairie standard
librairie standard en C++ : dans le namespace std : Fonctions I/O ( console, fichiers, ... ) Classes de base ( string, iterator, ... ) Conteneurs ( vector, list, ... ) Algorithmes standardisés ( tri, recherche, …) souvent la commande using namespace std; dans les fichiers .cpp .

82 Exemple d'interface : Bidon.h
#include "MaLib1.h" #include "MaLib2.h" #include <string> namespace util { class B public : std::string afficher(); private: Tp1::A a; std::string tmp; }; } // --- namespace util std::string afficher() using namespace std; string s; // traitement à faire return s; } On peut rajouter quelque chose dans un namespace déjà défini ailleurs. Ce using n'affecte que le corps de cette fonction.

83 Entrées et sorties : La famille des iostream
Collision de noms Entrées et sorties : La famille des iostream Une stream en C++ : séquence de caractères permettant de faire les opérations d'entrées/sorties. Une ostream gère les sorties inclut la définition de l'opérateur <<. Une istream gère les entrées inclut la définition de l'opérateur >>. ios iostream istream ostream

84 ostream, istream : streams principales
Une ostream peut être redirigée vers : l'écran (cout), la console d'erreur (cerr), le fichier d'historique (clog), un fichier (ofstream), un espace en mémoire (ostringstream, ostrstream). Une istream peut être redirigée vers : le clavier (cin), un fichier (ifstream), un espace en mémoire (istrstream). Plus de détails à venir.

85 Entrées et sorties cout << "Bonjour"; //Affiche Bonjour
Envoi et réception des informations de la console via des flux d'entrée et de sortie: input/output stream cout = flux de sortie pour l'affichage dans la console "console output" L'opérateur << envoi de l'information dans cout, donc vers la console. cout << "Bonjour"; //Affiche Bonjour

86 Entrées et sorties : cout
Enchaînement de plusieurs << dans une même instruction. Peut prendre tous les types de base en C++. Pas besoin de spécifier le format comme avec un printf. Un retour de chariot ( '\n' ) string nom = "Toto"; int age = 10; cout << "Bonjour " << nom << endl; cout << "Tu as " << age << " ans.";

87 Entrées et sorties : cin
= flux d'entrée de la console ce que tape l'utilisateur console input L'opérateur >> ( attention au sens ) reçoit l'information de cin, donc du clavier. cout << "Entrez votre nom : " ; string nom; cin >> nom; cout << "Entrez votre poids : " ; double poids; cin >> poids;

88 Entrées et sorties : cin
Quelques contraintes pour la saisie d'information: >> prend comme délimiteurs pour un string : espace, tab, RC Pour lire une chaîne de caractères comprenant des espaces ou des "tab" : string nomCompose; char buffer[256]; cin.getline(buffer, 255); nomCompose = buffer;

89 Entrées et sorties : cin
cin >> poids; ne "consomme pas" les délimiteurs cin.getline(buffer, 255); oui Solution: double poids; cin >> poids; int nombre; cin >> nombre; cin.ignore();//consomme le délimiteur qui est resté // dans le flux cin.getline(buffer, 255);//pas besoin de ignore // ici, getline consomme tout

90 Entrées et sorties cin/cout définis dans <iostream>
inclure l'entête cin/cout, les opérateurs << et >> et la classe string définis dans le namespace std. Dans un .cpp : ajouter au début du fichier using namespace std; Dans un .h : évitez le using, utilisez plutôt explicitement le nom du namespace avec ::

91 Entrées et sorties : exemple
#include <iostream> #include <string> using namespace std; void main() { cout << "Entrez votre nom : " ; string nom; cin >> nom; cout << "Entrez votre poids (Kg): " ; double poids; cin >> poids; cout << "Bonjour : " << nom << endl; cout << "Votre poids est " << poids << "kilo" << endl; } Problème si des espaces. Utilise plutôt un buffer et méthodes de cin.

92 I/O avec des fichiers Fichier : séquence d’octets terminée par une « marque de fin de fichier » (EOF). En C++ : vus comme des flux d’octets ou de caractères. ofstream : Pour l’écriture dans un fichier. ifstream : Pour la lecture à partir d’un fichier. Deux types de lecture/écriture : Mode texte : Peut être lu comme un document texte, caractère par caractère, mot par mot, ligne par ligne, etc. Mode binaire : décoder les informations, octet par octet. Se trouve dans l’entête <fstream>

93 Écriture en mode texte Pour ouvrir un fichier en écriture : déclarer un objet de type ofstream : 1er argument : le chemin et le nom du fichier. 2e argument : le type d’ouverture ios::out : Efface tout le contenu, si le fichier existait déjà. ios::app : Écrit après ce qu’il y a déjà dans le fichier. Si le fichier n’existe pas, il est créé dans les deux cas. On peut aussi déclarer un ofstream sans ouvrir le fichier. Pour ouvrir le fichier plus tard, utilisez la méthode open ofstream ofs("FichierAEcrire.dat",ios::out); ofstream ofs; // ... ofs.open("FichierAEcrire.dat",ios::app);

94 Pourra être relue comme une ligne entière
Exemple : //Ouverture d'un fichier en écriture ofstream ofs ("Moto.dat",ios::out); if (!ofs) { cerr << "Ouverture impossible" <<endl; return 1; } ofs << 2 << endl; // nombre de motos ofs << "Honda Shadow" << endl; ofs << 1986 <<endl; ofs << "Honda Valkyrie Rune" << endl; ofs << 2004 << endl; // Pour forcer la fermeture ofs.close(); Si le fichier ne peut être ouvert ( mauvais chemin ou déjà ouvert ), l’opérateur ! renvoie faux. Pourra être relue comme une ligne entière 2 Honda Shadow 1986 Honda Valkyrie Rune 2004

95 Lecture en mode texte Déclarer un objet de type ifstream
ios::in : lecture en mode texte, sans modification. ifstream ifs("FichierALire.dat", ios::in);

96 Exemple : Modèle : Honda Shadow Annee : 1986
{ ifstream ifs("Moto.dat",ios::in); if(!ifs) cerr << "Ouverture impossible" <<endl; return 1; } char ligne[256]; int nbMotos; ifs >> nbMotos; ifs.ignore(100, '\n'); for (int i=0; i<nbMotos; i++) ifs.getline(ligne,255); cout << " Modele : " << ligne << endl; ifs >> annee; cout << " Annee : " << annee << endl << endl; } // destructeur de ifs appelé, qui ferme le fichier Modèle : Honda Shadow Annee : 1986 Modèle : Honda Valkyrie Rune Annee :2004

97 Le passage de paramètre
Collision de noms Entrées/sorties Le passage de paramètre Types de passage de paramètres en C++ ? trois types : le passage par valeur, le passage par pointeur, le passage par référence (nouveauté par rapport au C). Quand utiliser chacun de ces types?

98 Coût de la copie lorsqu'on passe par valeur.
Le passage par valeur Permet de passer des valeurs sans que la fonction appelée puisse modifier celles-ci. pas d'«effet de bord» Les modifications sur les données passées n'ont pas d'influence sur les données originales. Coût de la copie lorsqu'on passe par valeur.

99 Le passage par valeur : Exemple
#include <iostream> #include <string> using namespace std; string MettreEnMajuscule (string texte) { unsigned int dim = texte.size(); for (int i=0; i<dim; i++) { texte[i] = (char)toupper(texte[i]); } return texte; } void main() { string nom = "programmation"; string NOM = MettreEnMajuscule(nom); cout << "Minuscule : " << nom << endl; cout << "Majuscule : " << NOM << endl; } Résultat: Minuscule : programmation Majuscule : PROGRAMMATION

100 Le passage par pointeur
Avec le langage C, Pour éviter le coût de la copie on passait les paramètres par pointeur. Approprié lorsque l'on veut que les données soient modifiées. Mais lorsqu'on ne veut pas …?!

101 Le passage par pointeur : Exemple
Passage par pointeur : Accès direct aux données originales #include <iostream> #include <string> using namespace std; string MettreEnMajuscule (string* texteP) { unsigned int dim = texteP->size(); for (int i=0; i<dim; i++) { (*texteP)[i] = (char)toupper((*texteP)[i]); } return *texteP; } void main() { string nom = "programmation"; string NOM = MettreEnMajuscule(&nom); cout << "Minuscule : " << nom << endl; cout << "Majuscule : " << NOM << endl; } Résultat: Minuscule : PROGRAMMATION Majuscule : PROGRAMMATION

102 Le passage par référence
Le passage par référence, tout comme le passage par pointeur, donne directement accès aux données originales. Pas de coût associé au passage par référence mais il y a risque de corruption des données par les fonctions appelées.

103 Le passage par référence : exemple
Passage par référence : Accès direct aux données originales #include <iostream> #include <string> using namespace std; string MettreEnMajuscule (string& texte) { unsigned int dim = texte.size(); for (int i=0; i<dim; i++) { texte[i] = (char)toupper(texte[i]); } return texte; } void main() { string nom = "programmation"; string NOM = MettreEnMajuscule(nom); cout << "Minuscule : " << nom << endl; cout << "Majuscule : " << NOM << endl; } Résultat: Minuscule : PROGRAMMATION Majuscule : PROGRAMMATION

104 Le passage par référence constante
Le langage C++ offre la possibilité de protéger les données originales en utilisant le passage par référence ET le mot const. Il n'y a plus de coût associé à la copie des données et il n'y a plus de risque de modification des données originales. Le passage par référence constante donne le même résultat que le passage par valeur, la copie en moins !

105 Le passage par référence constante : exemple
Passage par référence constante : Accès direct aux données originales sans pouvoir les modifier. #include <iostream> #include <string> using namespace std; string MettreEnMajuscule (const string& texte) { unsigned int dim = texte.size(); for (int i=0; i<dim; i++) { texte[i] = (char)toupper(texte[i]); } return texte; } void main() { string nom = "programmation"; string NOM = MettreEnMajuscule(nom); cout << "Minuscule : " << nom << endl; cout << "Majuscule : " << NOM << endl; } Résultat: Minuscule : programmation Majuscule : PROGRAMMATION

106 Conclusion Ne jamais utiliser le passage par valeur sauf pour les types de base du langage. Toujours utiliser le passage par référence constante si on désire que les données originales ne soient pas modifiées. Toujours utiliser le passage par référence si on désire que les données originales soient modifiées. Le passage par pointeur pourra être utilisé dans quelques rares cas, notamment pour le polymorphisme. (Nous y reviendrons)

107 Collision de noms Entrées/sorties Passage de paramètres Surcharge de méthode Les langages orientés objet permettent une première forme de polymorphisme: la surcharge de méthode (ou de fonction). Il est permis de créer plusieurs méthodes du même nom dans la classe pourvu qu'elles varient au niveau des paramètres. Lorsqu'une méthode surchargée est appelée, le compilateur sélectionne la bonne selon les paramètres: nombre, type, ordre. La surcharge doit être utilisée pour implanter des traitements similaires.

108 Surcharge de méthode (2)
Prenons un exemple d'une string: Le compilateur sélectionne la bonne méthode en fonction du type en paramètre. class string { public: (…) int rechercher (char c) const; int rechercher (const char* sP) const; int rechercher (const string& s) const; };

109 Surcharge de méthode (3)
Attention: le compilateur utilise seulement la liste des paramètres pour distinguer les fonctions de même nom. Le type de retour n'est pas pris en compte. class Quelconque { public: (…) bool methode1 (int p1, int p2); double methode1 (int p1, int p2); }; Pour le compilateur, ces deux méthodes sont identiques.

110 Paramètre par défaut (1)
Parfois, certaines méthodes ont besoins de plusieurs paramètres pour correctement faire le travail. Toutefois pour les cas simples ou les plus fréquents, ces paramètres supplémentaires sont toujours les mêmes. Il est possible d'utiliser la technique des paramètres par défaut.

111 Paramètre par défaut (2)
Soit une fonction qui permet d'imprimer un entier dans n'importe quelle base : 2, 10, 16… La plupart du temps se sera en base 10. void imprimer (int valeur, int base = 10); void main() { imprimer (31); imprimer (31, 10); imprimer (31, 16); imprimer (31, 2); } Résultat : F 11111

112 Paramètre par défaut (3)
Une autre implantation aurait pu utiliser la surcharge de fonction à la place : void imprimer (int valeur, int base); inline void imprimer (int valeur) { imprimer(valeur, 10); } void main() imprimer (31); imprimer (31, 10); imprimer (31, 16); imprimer (31, 2); Résultat : F 11111

113 Paramètre par défaut (4)
Les paramètres par défaut sont vérifiés à la compilation et évalués à l'exécution. Les paramètres par défaut doivent être fournis à partir des derniers arguments seulement. Correct : int foo(int a, int b=0, char* strP=0); Incorrect : int goo(int a=0, int b=0, char* strP); int hoo(int a=0, int b, char* strP=0);

114 Surcharge de méthode et paramètre par défaut
l'utilisation de la surcharge de méthode peut entrer en conflit avec l'utilisation des paramètres par défaut… class A { public: A(); A(const A& obj); A(int v1=0, int v2=0); private: int m_v1; int m_v2; }; Que peut-on dire à propos de ces constructeurs ? Il y aura conflit entre A() et A(int v1=0, int v2=0).

115 Questions En quoi se comparent deux méthodes surchargées?
Quel conflit peut survenir entre la surcharge de méthode et les paramètres par défaut?


Télécharger ppt "Concepts orientés objets"

Présentations similaires


Annonces Google