Introduction Le langage C++ est un des langages les plus célèbres au monde. Très utilisé, notamment dans le secteur des jeux vidéo qui apprécie ses performances et ses possibilités, le C++ est désormais incontournable pour les développeurs. Le C++ est le descendant du langage C. Ces deux langages, bien que semblables au premier abord, sont néanmoins différents. Le C++ propose de nouvelles fonctionnalités, comme la programmation orientée objet (POO). Elles en font un langage très puissant qui permet de programmer avec une approche différente du langage C. La petite histoire du C++ · 1958 : il y a longtemps, à l'époque où les ordinateurs pesaient des tonnes et faisaient la taille de votre maison, on a commencé à inventer un langage de programmation appelé l'Algol. · 1960-1970 : ensuite, les choses évoluant, on a créé un nouveau langage appelé le CPL, qui évolua luimême en BCPL, puis qui pris le nom de langage B · 1970 : puis, un beau jour, on en est arrivé à créer encore un autre langage qu'on a appelé... le langage C. Ce langage, s'il a subi quelques modifications, reste encore un des langages les plus utilisés aujourd'hui. · 1983 : un peu plus tard, on a proposé d'ajouter des choses au langage C, de le faire évoluer. Ce nouveau langage, que l'on a appelé "C++", est entièrement basé sur le C. Le langage C++ n'est en fait rien d'autre que le langage C avec plusieurs nouveautés. Il s'agit de concepts de programmation poussés comme la programmation orientée objet. C'est Bjarne Stroustrup, un informaticien originaire du Danemark, qui a conçu le langage C++. Insatisfait des possibilités offertes par le C, il a créé en 1983 le C++ en y ajoutant les possibilités qui manquaient selon lui. Bjarne Stroustrup est aujourd'hui professeur d'informatique à l'université du Texas, aux Etats-Unis. De nombreux langages de programmation se sont par la suite inspirés du C++. C'est notamment le cas du langage Java. Le langage C++, bien que relativement ancien, continue à être amélioré. Une nouvelle version, appelée C++1x, est d'ailleurs en cours de préparation. Il ne s'agit pas d'un nouveau langage mais d'une mise à jour du C++. Publicité En résumé · Le C++ est un descendant du C. Il le complète en rajoutant un certain nombre de possibilités. · Le C++ est un langage de bas niveau : il est plus proche du langage machine (le binaire) et peut parfois être assez complexe. · Le C++ est un langage extrêmement rapide, ce qui en fait le langage de prédilection de la plupart des jeux vidéo avides de performance Les concepts de base de la POO La POO s'articule autour des cinq concepts suivant que nous allons examiner plus en détail: • objet Conception de programme • classe • héritage • polymorphisme Implantation • liaison dynamique } } Les concepts de base de la POO Schéma comparatif – programmation procédurale versus objet Les concepts de base de la POO Objet • entités de base d'un programme OO • occupent de la place dans la mémoire de l'ordinateur • possède une adresse tout comme un enregistrement en Java, Visual Basic, etc… • un objet porte un nom et contient des données organisées sous forme de champs tout comme les enregistrements Les concepts de base de la POO Définition d’une application orientée objet Une application orientée objet = Définition d’un ensemble d’objets coopérants communicants - et concurrents - vivants indépendamment les uns des autres. Les concepts de base de la POO Classe • description statique, figée dans la programme ( c'est en fait le type de la donnée ) • la description d'une structure de données La déclaration d'une classe est voisine de celle d'une structure puisqu'en effet, il suffit: • de remplacer le mot-clé struct par class Créer une classe ? Je croyais qu'on allait apprendre à créer des objets, pourquoi tu nous parles de créer une classe maintenant ? Quel est le rapport ? Pour créer un objet, il faut d'abord créer une classe Vocabulaire : on dit qu'un objet est une instance d'une classe. C'est un mot très courant que l'on rencontre souvent en POO. Cela signifie qu'un objet est la matérialisation concrète d'une classe (tout comme une maison est la matérialisation concrète du plan de la maison). Les concepts de base de la POO Une classe est l’abstraction d’un ensemble d’objets qui possèdent une structure identique (liste des attributs) et un même comportement (liste des opérations). C’est un modèle décrivant le contenu et le comportement des futurs objets de la classe. Un objet est une instance d’une et d’une seule classe. La classe est en fait le squelette. (tout comme un struct) Concept objets Une classe est constituée : - de variables, ici appelées attributs (on parle aussi de variables membres) - de fonctions, ici appelées méthodes (on parle aussi de fonctions membres) Regardons maintenant un exemple de déclaration d’une classe La classe Avion La déclaration d’une classe Donnée du problème: je veux définir une classe qui contient les données «privées» suivantes: - immatriculation de l’appareil ( chaînes de caractères de 5); - type d’appareil (chaînes de caractères de 30); - poids de l’appareil ( virgule flottante ). de plus, je veux la méthode de type «privée» suivante: erreur qui ne retourne pas de paramètre et qui reçoit un pointeur sur une chaîne. La classe «avion» doit aussi contenir les deux méthodes «publiques»: - initialisation qui ne retourne pas de paramètre et qui reçoit 3 paramètres ( un tableau de char, un pointeur de char, et un float ). - affiche qui ne retourne et reçoit rien. La déclaration d’une classe Solution au problème. #include <iostream> /* fichier d'entête se rapportant au cin & cout */ class Avion { public : void initialisation(char [], char [], float); void affiche(); private : char _immatriculation[6], _type[31]; float _poids; void erreur(char *); }; La déclaration d’une classe Convention suggérée • la première lettre du nom de la classe en majuscule • la liste des membres publics en premier • les nom des méthodes en minuscules • le caractère _ comme premier caractère du nom d’une donnée membre Instanciation d’une classe De façon similaire à une struct, le nom de la classe représente un nouveau type de donnée. On peut donc définir des variables de ce nouveau type; on dit alors que l’on crée des objets ou des instances de cette classe. Exemple: Avion av1; // une instance simple (statique) Avion compagnie[10]; // un tableau d’instance av2 = new Avion; // création (dynamique) d’une instance Utilisation des objets Après avoir créé une instance, on peut accéder aux attributs et méthodes de la classe. Cet accès se fait comme pour les structures, c’est-à-dire en utilisant l’opérateur . (point) . Exemple: av1.init("FGBCD" , “TB20” , 1.47 ); av2.init("FGDEF" , “aTr 42” , 80.0 ); av1.affiche(); av2.affiche(); Revenons à notre problème sur les avions int main(void) { // Déclaration des variables de lecture char avion_immatriculation[6]; char avion_type[31]; float avion_poids; int flag = 0; Instanciation de la classe // Instanciation de la classe Avion av1; // une instance simple (statique) while(flag != 1) { cout << "Code d'immatriculation (zzz pour terminer) : "; cin >> avion_immatriculation; fflush(stdin); // vide le tampon associé au flux d’entrée Programme avions – suite du main if ( strcmp(avion_immatriculation,"zzz") == 0) { flag = 1; continue; } cout << "Type d'avion : "; cin.getline( avion_type, sizeof(avion_type), '\n'); cout << "Poids de l'avion : "; cin >> avion_poids; av1.initialisation( avion_immatriculation, avion_type, avion_poids); av1.affiche(); } cout << " \n\n\n\n\n" ; system(" pause "); } Regardons maintenant le code de ces deux méthodes Programme avions – contenu des «2» méthodes void Avion::initialisation(char m[], char t[], float p) { if ( strlen(m) != 5 ) { erreur("Immatriculation invalide"); strcpy_s(_immatriculation, "?????"); } else strcpy_s(_immatriculation, m); strcpy_s(_type, t); _poids = p; } void Avion::erreur(char *message) { cout << message << endl; cout << "Appuyer sur une touche ..." ; system(" pause "); cout << endl << endl; } Programme avions – contenu des «2» méthodes void Avion::affiche() { cout << _immatriculation << " " << _type; cout << " " << _poids << endl; } CONSTRUCTEURS Le constructeur est une fonction membre spécifique de la classe qui est appelée implicitement à l'instanciation de l'objet, assurant ainsi une initialisation correcte de l'objet. Ce constructeur est une fonction qui porte comme nom, le nom de la classe et qui ne retourne pas de valeur (pas même un void). Exemple : class Nombre { public : Nombre(); // constructeur par défaut // ... private : int _i; }; Nombre::Nombre() { _i = 0; } Exemple de constructeurs Les concepts de base de la POO L'instanciation est l'action d'instancier, de créer un objet à partir d'un modèle (classe). Elle est réalisée par la composition de deux opérations : l'allocation et l'initialisation. • L'allocation consiste à réserver un espace mémoire au nouvel objet. • L'initialisation consiste à fixer l'état du nouvel objet. Cette opération fait par exemple appel à l'un des constructeurs de la classe de l'objet à créer De manière plus générale, fabriquer un exemplaire d'un élément à partir d'un modèle qui lui sert en quelque sorte de moule. Dans le cas d'un patron (template en anglais), la fabrication requiert un paramétrage, c'est-à-dire une fixation des valeurs des paramètres inclus dans le patron. Les concepts de base de la POO Classe instanciant 2 objets _NumVéhicule: 1026 _Marque= « Toyota » _Puissance= 8 _Vitesse maximale= 220 _Vitesse courante= 160 _NumVéhicule: 1105 _Marque= « Ford » _Puissance= 7 _Vitesse maximale= 180 _Vitesse courante= 150 Véhicule I N S T A N C I A T I O N -_NumVéhicule : Entier -_Marque : Chaine -_Puissance : Entier -_Vitesse maximale: Entier -_Vitesse courante: Entier +Créer un véhicule ( ) +Détruire un véhicule ( ) +Démarrer ( ) +Accélérer (Taux : Entier) +Avancer ( ) +Reculer ( ) Accès membres acétate 38 Les concepts de base de la POO La notion de classe est centrale en programmation par objets en C++. Une classe est un ensemble d’objets. Exemple: la classe “voiture” de l’acétate précédente est l’ensemble des objets “voiture”. On appelle instance d’une classe un objet appartenant à celleci. Les deux voitures de l’acétate précédente ( la Toyota et la Ford ) sont des instances de la classe “voiture”. Les concepts de base de la POO La description des éléments constituants une classe se fait par un ensemble d’attributs et de méthodes . Les attributs sont destinées à recevoir des valeurs. Les méthodes sont destinées à recevoir du code. Les concepts de base de la POO La définition syntaxique de la classe est composée de deux parties: Entête Composée du mot réservé class suivi du nom de la classe. Corps Délimité par une paire d’accolades et suivi d’un point-virgule. Class Fenetre { public: void deplace(int nouv_x, int nouv_y); private: int _posx,_posy, _hauteur, _largeur; char _titre_fenetre[31]; }; Accès aux membres Accueil Les concepts de base de la POO L’encapsulation L'encapsulation est un mécanisme consistant à rassembler les données et les méthodes au sein d'une structure en cachant l'implémentation de l'objet, c'est-à-dire en empêchant l'accès aux données par un autre moyen que les services proposés. L'encapsulation permet donc de garantir l'intégrité des données contenues dans l'objet. Comment aborder l’approche objet ? Principe de continuité: les mêmes concepts sont utilisés tout au long du cycle de vie (Analyse, Conception, Programmation et Implantation) Principe de la réutilisabilité : Réduction du nombre de nom par l’encapsulation. Classification des éléments du logiciel (utilisation des classes) Suppression des redondance (héritage) Comment aborder l’approche objet ? Analyse fonctionnel (Merise) ? Mauvaise approche. Ce type d’analyse est orientée traitement (unité de traitement, fonction) ce qui est contraire à l’approche orientée objet. Méthodologie UML ? Bonne approche. La plus répandue. Comment aborder l’approche objet ? UML n'est une méthodologie orientée objet, mais un langage de description des objets UML a été créé par James Rumbaugh, Grady Booch et Yvar Jacobson UML est un langage de modélisation rigoureux pour la modélisation de systèmes complexes : Concepts précis Sémantique claire Notations non ambiguës Langage de description de contraintes : OCL Diagrammes UML pour représenter les données Il existe 13 diagrammes UML de la version 2.5 permettant de représenter de façon graphique et en respectant un standard. Dans le cadre du cours de structure de données, nous utiliserons le diagramme de classes. ( voir exemple ) Les autres diagrammes seront vus dans le cadre du cours “Développement objet” prévu à la session 4 du DEC. MODE DE DERIVATION Lors de la définition de la classe dérivée il est possible de spécifier le mode de dérivation par l'emploi d'un des mots-clé suivants : public, protected ou private. Ce mode de dérivation détermine quels membres de la classe de base sont accessibles dans la classe dérivée. Au cas où aucun mode de dérivation n'est spécifié, le compilateur C++ prend par défaut le mot-clé private pour une classe et public pour une structure. Les membres privés de la classe de base ne sont jamais accessibles par les membres des classes dérivées Héritage public : Il donne aux membres publics et protégés de la classe de base le même statut dans la classe dérivée. Exemple : class Vehicule { public: void pub1(); protected: void prot1(); private: void priv1(); }; class Voiture : public Vehicule { public: int pub2() { pub1(); // OK prot1(); // OK priv1(); // ERREUR } }; Voiture safrane; safrane.pub1(); // OK safrane.pub2(); // OK Héritage privé : Il donne aux membres publics et protégés de la classe de base le statut de membres privés dans la classe dérivée . Exemple : class String { public: int length(); // ... }; class Telephone_number : private String { void f1() { // ... l = length(); // OK }; Telephone_number tn; cout << tn.length(); // ERREUR Héritage protégé : Il donne aux membres publics et protégés de la classe de base le statut de membres protégés dans la classe dérivée. Exemple : REDEFINITION DE METHODES DANS LA CLASSE DERIVEE HÉRITAGE MULTIPLE Il permet de créer une classes dérivées à partir de plusieurs classes de base. Pour chaque classe de base, on peut définir le mode d’héritage. Exemple: class A { public: void fa() { /* ... */ } protected: int _x; }; class B { public: void fb() { /* ... */ } protected: int _x; }; class C: public B, public A { public: void fc(); }; ... ... HÉRITAGE MULTIPLE (suite) – Si deux membres hérités ont le même nom alors on doit utiliser l'opérateur de portée – Exemple: supposons que A et B possède une variable publique entière _x class sous-classe: public A, public B{ ... }; sous-classe V; V.A::_x=0; V.B::_x=1; Illustration de l’héritage multiple Ordre d’appel des constructeurs Une liste d'initialisation s'utilise lors de la définition d'un constructeur Syntaxe : nom_classe::nom_constructeur( args ... ) : liste_d_initialisation { // corps du constructeur } Exemple : X::X(int a, int b, Y y) : _x( a ) , _y( y ) , _z( b ) { // rien d'autre à faire } Les destructeurs sont appelés dans l'ordre inverse de celui des constructeurs. DECLARATION DES FONCTIONS •Le langage C++ impose au programmeur de déclarer le nombre et le type des arguments de la fonction. •Ces déclarations sont identiques aux prototypes de fonctions de la norme C-ANSI. •Cette déclaration est par ailleurs obligatoire avant utilisation •La déclaration suivante int f1(); où f1 est déclarée avec une liste d'arguments vide est interprétée en C++ comme la déclaration int f1(void); •Une fonction dont le type de la valeur de retour n'est pas void, doit obligatoirement retourner une valeur. PASSAGE PAR REFERENCE Lire une information jusqu'à ce que l'usager appuie la touche "Entrée " ( semblable au gets en C standard )