26
D. DUBOIS Mars 2016 en résumé… Prérequis : - Langage C - Java / POO

Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

  • Upload
    others

  • View
    7

  • Download
    1

Embed Size (px)

Citation preview

Page 1: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Mars 2016

en résumé…

Prérequis : - Langage C

- Java / POO

Page 2: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 2 / 33

I. Introduction ................................................................................................................... 3

1. Références ................................................................................................................................................. 3 2. Présentation .............................................................................................................................................. 3 3. Premier programme « Hello world » en C++ ............................................................................................ 4

II. Variables ........................................................................................................................ 5

1. Règles de base ........................................................................................................................................... 5 2. Conventions d’usage ................................................................................................................................. 5 3. Type de variable ........................................................................................................................................ 5 4. Déclaration d’une variable ........................................................................................................................ 6 5. Déclarer une constante ............................................................................................................................. 6 6. Déclarer une chaine de caractères ........................................................................................................... 6

III. Les références (&) ............................................................................................................ 7

IV. Lecture depuis la console .................................................................................................. 7

V. Arithmétique ................................................................................................................. 8

VI. Les structures de contrôle.................................................................................................. 8

VII. Les fonctions ................................................................................................................... 8

VIII. Les tableaux ................................................................................................................... 9

1. Les tableaux statiques .............................................................................................................................. 9 2. Les tableaux dynamiques (vector) ............................................................................................................ 9

IX. Les surcharges & les modèles.............................................................................................. 11 1. La surcharge (overloading functions) ..................................................................................................... 11 2. Le modèle (Function Templates) ............................................................................................................ 11

X. C++ et la POO ............................................................................................................... 13

1. Les classes ............................................................................................................................................... 13 2. La surcharge d’opérateurs ...................................................................................................................... 19 3. L’héritage ................................................................................................................................................ 21 4. Le polymorphisme ................................................................................................................................... 24

XI. Exercices ....................................................................................................................... 26

1. Exercice 1 : trier/échanger ...................................................................................................................... 26 2. Exercice 2 : Référence ............................................................................................................................. 26 3. Exercice 3 : Recopie ................................................................................................................................. 26 4. Exercice 4 : String ................................................................................................................................... 26 5. Exercice 5 : Classe ................................................................................................................................... 26 6. Exercice 6 : classe .................................................................................................................................... 26 7. Exercice 7 : surcharge d’opérateurs ....................................................................................................... 26

XII. Corrigés des exercices ....................................................................................................... 27

1. Exercice 1 ................................................................................................................................................ 27 2. Exercice 2 ................................................................................................................................................ 28 3. Exercice 3 ................................................................................................................................................ 29 4. Exercice 4 ................................................................................................................................................ 30 5. Exercice 5 ................................................................................................................................................ 31 6. Exercice 6 ................................................................................................................................................ 32 7. Exercice 7 ................................................................................................................................................ 33

Page 3: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 3 / 33

I. Introduction

1. Références

Prérequis : Langage C & POO

Référence :

Références Web :

o http://www.cplusplus.com

o http://fr.cppreference.com

Références bibliographiques :

2. Présentation

Langage développé par Bjarne STROUSTRUP (années 80)

Evolution du langage C avec l’apport de la POO

Langage de programmation les plus populaires avec le C et le JAVA

Langage normalisé - Standard actuel : ISO/IEC 14882:2011 (Maj : ISO/IEC 14882:2014)

Multiplateforme / multi systèmes d’exploitation

Langage de programmation compilé

Permet différents types de programmation

o Programmation procédurale (ou modulaire) : découpe d’un programme en série de

fonction (ou procédures). une procédure (routine ou fonction) contient une série d'étapes à

réaliser. Elle peut être appelée à n’importe quelle étape de l’exécution du programme ou à

partir d’autres procédures ou d’elle-même (récursivité)

o Programmation Orientée Objet : Représenter des objets et leurs relations entre eux. Un

objet = concept possédant une structure et un comportement et interagit avec d’autres objets

o Programmation générique : définir des algorithmes identiques qui traitent des données

de types différents (équivalent au polymorphisme)

La syntaxe du C++ est proche du langage C : découpage du code en module, utilisation de

fichiers inclus,….

Les principaux ajouts par rapport au langage C :

o le type de données bool (booléen) ;

o les références

o les paramètres par défaut dans les fonctions

o les référentiels lexicaux (namespace) et l'opérateur de résolution « :: »

o les classes - POO

o la surcharge des opérateurs

o les templates

o la gestion d'exceptions

o les string

o …

Page 4: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 4 / 33

3. Premier programme « Hello world » en C++

Variante 1

#include<iostream>

int main()

{

// affichage d’un message

std::cout << "Hello world!\n";

return 0 ;

}

Variante 2

#include<iostream>

using namespace std ;

int main()

{

// affichage d’un message

cout << "Hello world!\n";

return 0 ;

}

#include<iostream> C'est une directive de préprocesseur.

Rôle : charger les fonctionnalités du C++ pour effectuer certaines actions ; ce sont

des extensions du langage appelées bibliothèques.

Ici le fichier iostream (Input Output Stream) permet d'utiliser une bibliothèque

d'affichage de messages à l'écran dans une console. Il permet également de

récupérer ce que saisit l’utilisateur au clavier

using namespace std Indique dans quel lot de fonctionnalités le fichier source va chercher les fonctions

utilisées. Quand on charge plusieurs bibliothèques, chacune va proposer de

nombreuses fonctionnalités qui ont parfois le même nom. Pour éviter la confusion

il existe les espaces de noms (namespaces) qui sont des sortes de dossiers à noms.

Ici on indique qu’on utilise l'espace de noms std : il correspond à la bibliothèque

standard (std) livrée par défaut avec le langage C++ et dont iostream fait partie.

Namespace est similaire à l’utilisation des packages en Java

int main() {

...

}

Les accolades déterminent le début et la fin de la fonction main.

La fonction main retourne un entier suite à son exécution

Tous les programmes commencent par la fonction main

cout << "Hello world!\n"; Ici, la première instruction de la fonction main

cout : afficher un message à l’écran

chaque instruction se termine par un point-virgule

Autre exemple :

cout << "Bonjour" << endl << "tout le monde" << endl ;

"Bonjour" et "tout le monde": c’est le message à afficher ;

endl : crée un retour à la ligne dans la console.

return 0 ; Instruction qui clôt généralement les fonctions.

Ici, la fonction main renvoie 0 pour indiquer que tout s'est bien passé

// affichage d’un message // permet d’écrire un commentaire court sur une seule ligne

/* permet d’écrire un commentaire

sur plusieurs lignes */

Page 5: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 5 / 33

II. Variables

Une variable est une information stockée en mémoire.

Il existe différents types de variables en fonction de l'information à stocker : int, char, bool…

Une variable doit être déclarée avant utilisation. Sa valeur peut être affichée avec cout.

1. Règles de base

Les noms de variables sont constitués de lettres, de chiffres et de l’underscore uniquement ;

le premier caractère doit être une lettre majuscule ou minuscule ;

Les accents et les espaces dans le nom sont interdits ;

Le C++ est sensible à la casse : il fait la différence entre les majuscules et les minuscules.

2. Conventions d’usage

Pour plus de lisibilité, utiliser des noms de variables qui décrivent ce qu'elles contiennent

(ageDuCapitaine pour désigner la variable qui contiendra l’âge du capitaine)

les noms de variables commencent par une minuscule ; si le nom se décompose en plusieurs

mots, ceux-ci sont collés les uns aux autres ;

chaque nouveau mot (excepté le premier) commence par une majuscule.

3. Type de variable

Type booléen

o bool - type capable de contenir l'une des deux valeurs : vrai (true) ou faux (false).

Types de caractères

o signed char - type pour la représentation des caractères signés.

o unsigned char - type pour la représentation des caractères non signés.

o char - type représentant un caractère (équivalent à signed char )

o wchar_t - type représentant caractère large. (ex. UTF-8)

o char16_t - type représentant un caractère UTF-16. (depuis C++11)

o char32_t - type représentant un caractère UTF-32. (depuis C++11)

Type entier

Type de variable

Largeur (bits) en mémoire

Valeurs C++

Win16

API

Win32

API

Unix

Win64

API Unix

short, short int

signed short, signed short int 16 -32 768 à 32 767

unsigned short, unsigned short int 0 à 65535

int, signed,

signed int 16 16 32 32 32

-32 768 à 32 767 ou

-2 147 483 648 à 2 147 483 647

unsigned,

unsigned int

0 à 65535 ou

0 à 4 294 967 295

long, long int,

signed long, signed long int 32 32 32 32 64

-2 147 483 648 à 2 147 483 647 ou

-9 223 372 036 854 775 808 à 9 223 372 036 854 775 807

unsigned long

unsigned long int

0 à 4 294 967 295 ou

0 à 18 446 744 073 709 551 615

long long

long long int (C++11)

signed long long

signed long long int 64

-9 223 372 036 854 775 808 à 9 223 372 036 854 775 807

unsigned long long (C++11)

unsigned long long int 0 à 18 446 744 073 709 551 615

Page 6: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 6 / 33

Type à virgule flottante :

o float : type à virgule flottante à précision simple = type IEEE-754 32 bits.

Valeurs : ± 3.4 · 10± 38

o double : type à virgule flottante à précision double = type IEEE-754 64 bits.

Valeurs : ± 1.7 · 10± 308

o long double : type à virgule flottante à précision étendue = 80-bit x87

4. Déclaration d’une variable

a. Sans initialisation

TYPE NOM ; // déclaration d’une variable nommée NOM de type TYPE

b. Déclaration d’une variable avec initialisation

Les trois initialisations suivantes sont strictement équivalentes. Il est conseillé d'utiliser la

première ou la seconde pour respecter la norme C++

TYPE NOM (VALEUR) ; // syntaxe d’initialisation d’une variable en C++

TYPE NOM {VALEUR} ; // révision du C++ en 2011

TYPE NOM = VALEUR ; // syntaxe d’initialisation d’une variable en C

c. Exemple sur les variables

#include <iostream>

using namespace std;

int main()

{

string nomJoueur ; // déclaration d’une chaine de caractère

int nombreJoueurs ; // déclaration d’un entier

bool estGagnant ; // déclaration d’un booléen

int ageDuCapitaine(61); // déclaration et initialisation d’un entier

double pi(3.14169); // déclaration et initialisation d’un double

bool estVerifie(false); // valeurs possible pour type bool : true ou false

char lotte('a'); // apostrophe pour déclarer un char

string nomUser("dado"); // guillemet pour déclarer une chaîne

int a(-1),b(12),c(0) ; // déclaration de trois entiers en cascade

a = b ; // affectation de la valeur de b à a

pi = 3.1 ; // changement de la valeur de pi

cout << "Le capitaine a " << ageDuCapitaine << " ans." << endl; // affichage

return 0;

}

5. Déclarer une constante

On déclare une variable normalement et on ajoute le mot-clé const entre le type et le nom :

int const maxNiveaux(10) ;

double const pi(3.14);

unsigned int const pointVieMax(1000);

6. Déclarer une chaine de caractères

Trois façons pour déclarer et initialiser une chaine de caractères

string mystring = "Vers l’infini et au-delà";

string mystring("To infinity and beyond");

string mystring {"Buzz lightyear"};

Page 7: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 7 / 33

III. Les références (&)

Une variable est un emplacement mémoire et cette variable est accessible par son nom dans

le programme.

Il est possible d’attribuer à une variable plusieurs « étiquettes » ce qui procure un autre

moyen d’accéder au même emplacement mémoire que la variable nommée. C’est ce qu’on

appelle la référence. La référence doit impérativement être du même type que la variable

à laquelle elle fait référence.

int ageDuCapitaine(61); // Déclaration et initialisation d’un entier

int& maVar(ageDuCapitaine); // Déclaration d'une référence nommée maVar

// maVar fait référence à ageDuCapitaine

int& autreVar = ageDuCapitaine ; //autreVar est une référence initialisée à ageDuCapitaine

cout << "le capitaine a " << ageDuCapitaine << " ans." << endl; // via variable

cout << "le capitaine a " << maVar << " ans. " << endl; // via référence

IV. Lecture depuis la console

flux sortant : cout les chevrons associés :

flux entrant : cin les chevrons associés :

#include <iostream>

using namespace std;

int main()

{ cout << "Quel age avez-vous ?" << endl;

int ageUtilisateur(0);

cin >> ageUtilisateur;

cout << "Vous avez " << ageUtilisateur << " ans !" << endl;

return 0;

}

Attention : le problème des espaces dans les chaines de caractères saisies (comme en C)

Quand on valide une saisie par la touche Entrée, l'ordinateur copie en mémoire ce qui a été tapé

par l'utilisateur… MAIS s’arrête au premier espace ou retour à la ligne rencontré.

Pour les nombres, pas de problème (puisqu'il n'y a pas d'espace dans les nombres)

Pour les string, problème : Il peut y avoir un ou plusieurs espaces dans une chaîne de

caractères : il faut alors utiliser la fonction getline()

Remplacer la ligne cin nomUtilisateur; par getline(cin, nomUtilisateur);

Quand on mélange l'utilisation des chevrons et de getline(), il faut toujours placer

l'instruction cin.ignore() après la ligne cin …

#include <iostream>

#include <string>

using namespace std;

int main()

{

cout << "Quel est votre taille ?" << endl;

double tailleUtilisateur(-1.0);

cin >> tailleUtilisateur;

cin.ignore();

cout << "Quel est votre nom ?" << endl;

string nomUtilisateur("Sans nom");

getline(cin, nomUtilisateur);

cout << "Vous vous appelez " << nomUtilisateur << " et vous

mesurez " << tailleUtilisateur << "m" << endl;

return 0;

}

Page 8: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 8 / 33

V. Arithmétique

Opérateurs arithmétique, incrémentation, décrémentation Voir langage C

Utilisation des fonctions mathématiques comme sqrt(), fabs, ceil(),floor(), pow(),sin(),…

#include<cmath>

VI. Les structures de contrôle

if() else , switch(), while(), do...while(), for() Voir langage C

Variante pour l’initialisation en C++ dans la boucle for :

#include <iostream>

using namespace std;

int main ()

{

for (int n=10; n>0; n--) { // déclaration du type dans la boucle for

cout << n << ", ";

}

cout << "GO!\n";

}

La boucle a aussi une autre syntaxe qui est utilisée pour les intervalles:

#include <iostream>

#include <string>

int main ()

{

std::string str {"Hello les ITI !"};

for (char c : str)

{

std::cout << c << ' ' ; // H e l l o l e s I T I !

}

std::cout << '\n';

}

VII. Les fonctions

Créer et utiliser une fonction Voir langage C

Passage par valeur Voir langage C

Passage par référence :

Code C++

void echange(int& x, int& y)

{

int buffer = x;

x = y;

y = buffer;

}

int main()

{

int a(3), b(5);

cout << "a = " << a << endl ;

cout << "b = " << b << endl ;

echange(a,b);

cout << "a = " << a << endl ;

cout << "b = " << b << endl ;

return 0 ;

}

Code C

void echange (int *x, int *y)

{

int buffer = *x;

*x = *y;

*y = buffer;

}

int main()

{

int a = 3, b = 5;

printf("a = %d\n",a);

printf("b = %d\n",b);

echange (&a, &b);

printf("a = %d\n",a);

printf("b = %d\n",b);

return 0 ;

}

Page 9: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 9 / 33

VIII. Les tableaux

1. Les tableaux statiques

Déclaration d’un tableau statique : TYPE NOM [taille] ;

Exemple:

#include <iostream>

using namespace std;

double moyenne(double tableau[] , int taille )

{

double moy(0) ;

for (int i(0);i<taille ;i++)

moy += tableau [i] ;

moy /= taille ;

return moy ;

}

int main ()

{

double notes[5] ; // déclaration d’un tableau de 5 « double »

notes[0] = 12.5 ;

notes[1] = 19.5 ;

notes[2] = 8. ;

notes[3] = 15. ;

notes[4] = 5.3 ;

cout << "Moyenne : " << moyenne(notes,5) << endl ;

return 0;

}

2. Les tableaux dynamiques (vector)

Un tableau dynamique est un tableau dont la taille peut varier. Elle n’est pas fixée comme

un tableau statique

Pour utiliser les tableaux dynamiques, il faut ajouter la ligne #include<vector> en début

de programme

Déclaration d’un tableau dynamique : VECTOR<TYPE> NOM (taille) ;

a. Exemple de déclaration :

#include <iostream>

#include <vector>

using namespace std;

int main ()

{

vector<int> t(5) ; // t est un tableau de 5 entiers

vector<int> tab(5,3) ; // tab est un tableau de 5 entiers valant tous 3

vector<string> listeNoms(10,"anonyme") ; // tableau de 10 string valant « anonyme »

vector<double> tab ; // création d’un tableau tab de 0 nombre à virgule

return 0 ;

}

Page 10: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 10 / 33

b. Exemple pour accéder aux éléments d’un tableau

int const nbHighScores(3) ; // taille du tableau

vector<int> highScores(nbHighScores) ; // déclaration du tableau highScores

highScores[0] = 813652 ;

highScores[1] = 71294 ;

highScores[2] = 58693 ;

c. Changer la taille du tableau

#include <iostream>

#include<vector>

using namespace std;

int main ()

{

vector<int> tableau(3,2) ; // déclaration du tableau de 3 entiers valant tous 2

tableau.push_back(8) ; // ajout d’une 4ème case au tableau qui contient 8

tableau.push_back(4) ; // ajout d’une 5ème case au tableau qui contient 4

tableau.push_back(18) ; // ajout d’une 6ème case au tableau qui contient 18

tableau.pop_back() ; // suppression de la dernière case du tableau

for (int i(0);i<tableau.size();i++)

cout << tableau[i] << endl;

return 0 ;

}

d. Vector : Les méthodes

int size() : renvoie la taille du vecteur (son nombre d’éléments)

bool empty() : indique si le vecteur est vide ( vect.empty() vect.size() == 0 )

void clear : vide le vecteur en supprimant tous ses éléments

void pop_back() : supprime le dernier élément du vecteur

void push_back(const type element) : ajoute element à la fin du vecteur

type front() : renvoie une référence vers le 1er élément du vecteur (vect.front()vect[0])

type back() : renvoie une référence vers le dernier élément du vecteur

e. Les tableaux multidimensionnels

int tableau[5][4] ;

double grilledelaudela[7][8][1][4][8] ;

vector<vector<int> > grille ;

grille.push_back(vector<int>(5)) ; // ajoute une ligne de 5 cases à la grille

grille.push_back(vector<int>(3,4)) ; // ajoute une ligne de 3 cases contenant 4

grille[0].push_back(8) ; // ajoute une case contenant 8 à la première ligne du tableau

grille[2][3] = 9 ; // change la valeur de la cellule (2,3) de la grille

f. Les strings comme tableaux

#include <iostream>

#include<string>

using namespace std ;

int main()

{

string user("Lucien") ;

user[0]= 'J' ; // modification de la première lettre

user[2]= 'L' ; // modification de la troisième lettre

cout << "Vous etes : " << user << endl ;

return 0 ;

}

Page 11: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 11 / 33

IX. Les surcharges & les modèles

1. La surcharge (overloading functions)

En C ++, deux fonctions différentes peuvent avoir le même nom

si leurs paramètres sont différents : o soit parce qu'elles ont un certain nombre de paramètres différents

o soit parce que l'un de leurs paramètres est d'un type différent.

#include <iostream>

using namespace std;

int calcul (int a, int b)

{

return (a*b);

}

double calcul (double a, double b)

{

return (a/b);

}

int main ()

{

int x=10,y=30;

double z=15.0,w=27.0;

cout << calcul (x,y) << '\n';

cout << calcul (z,w) << '\n';

return 0;

}

.

2. Le modèle (Function Templates)

Exemple qui se prête à l’application des templates:

// overloaded functions

#include <iostream>

using namespace std;

int sum (int a, int b)

{

return a+b;

}

double sum (double a, double b)

{

return a+b;

}

int main ()

{

cout << sum (10,20) << '\n';

cout << sum (1.0,1.5) << '\n';

return 0;

}

Ici, la somme est surchargée avec des types de

paramètres différents, mais avec le même

corps d’instructions.

Cette fonction pourrait être alors surchargée

par beaucoup plus de types.

C++ a la capacité de définir des fonctions avec

des types génériques, connus sous le nom des

modèles de fonction.

Déclaration d’un modèle :

template <paramètres> Fonction déclaration

Les paramètres de modèle sont une série de paramètres séparés par des virgules.

Attention : Cet exemple montre deux fonctions qui portent le même nom et qui ont ici des comportements différents sur les variables : Ce qui n’est vraiment pas une bonne chose ! Généralement elles sont censées avoir un comportement identique sur les variables

Page 12: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 12 / 33

Exemple 1:

#include <iostream>

using namespace std;

template <typename T>

T sum (T a, T b)

{

T result;

result = a + b;

return result;

}

int main ()

{

int i=5, j=6, k;

double f=2.0, g=0.5, h;

k=sum<int>(i,j);

h=sum<double>(f,g);

cout << k << '\n';

cout << h << '\n';

// autre ecriture

k=sum(i,j);

h=sum(f,g);

cout << k << '\n';

cout << h << '\n';

return 0;

}

Exemple 2:

#include <iostream>

using namespace std;

template < typename T, typename U>

bool egalite (T a, U b)

{

return (a==b);

}

int main ()

{

if (egalite<int,double>(10,10.1))

cout << "x = y \n";

else

cout << "x != y\n";

// autre ecriture

if (egalite(10,10.0))

cout << "x = y \n";

else

cout << "x != y\n";

return 0;

}

Exemple 3:

#include <iostream>

using namespace std;

template <typename T>

T maximum (const T& a, const T& b)

{

if (a>b)

return a ;

else

return b ;

}

int main ()

{

// utilise la version double

double pi(3.14) ;

double e(2.71) ;

cout << maximum<double>(pi,e) ;

cout << endl ;

// utilise la version int

int rdc(0) ;

int cave(-1) ;

cout << maximum<int>(rdc,cave) ;

cout << endl ;

return 0;

}

Exemple 4:

#include <iostream>

using namespace std;

template < typename T, typename S>

S moyenne (T tableau[],int taille)

{

S somme(0) ;

for (int i(0);i<taille;++i)

somme += tableau[i] ;

return somme/taille ;

}

int main ()

{

int tab[5] = {5,7,3,4,5} ;

cout << "Moyenne :" ;

cout << moyenne<int,double>(tab,5) ;

cout << endl ;

return 0;

}

Page 13: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 13 / 33

X. C++ et la POO

Une classe est constituée :

o de variables appelées attributs ou variables membres

o de fonctions appelées méthodes ou fonctions membres

o Il n’y a pas d’ordre mais il est d’usage de commencer par la déclaration des attributs

o Les droits d'accès

1. Les classes

Code minimal pour créer une classe :

// Création de la classe Joueur

class Joueur

{

} ; // Ne pas oublier le point-virgule

a. Les attributs :

C’est ce qui caractérise la classe, ici le Joueur. Ce sont des variables qui peuvent évoluer

au fil du programme.

class Joueur

{

int niveauVie ; // niveau de vie du joueur

int niveauMagie ; // niveau de magie du joueur

string armeJoueur ; // arme du joueur

int puissanceArme ; // puissance de l’arme du joueur

} ;

b. Les méthodes :

Ce sont les actions que peut effectuer le joueur. Les méthodes lisent et modifient les attributs

class Joueur

{

void diminuerVie (int vieEnMoins) { … } // diminution de la vie du joueur

void augmenterVie (int vieEnPlus) { … } // augmenter la vie du joueur

void attaquer (Joueur &cible) { … } // Attaquer un autre joueur

void changerArme (string nomNouvelleArme,int puissanceNouvelleArme) { … }

bool estVivant(){ … } // vérification que le joueur est vivant

} ;

c. Droits d’accès et encapsulation

Chaque attribut ou méthode d’une classe peut posséder son propre droit d’accès. Il existe 2

principaux droits d’accès différents :

public : l'attribut ou la méthode peut être appelé depuis l'extérieur de l'objet.

private : l'attribut ou la méthode ne peut pas être appelé depuis l'extérieur de

l'objet.

Par défaut (sans spécification aucune), tous les éléments d'une classe sont private.

Principe d’encapsulation :

Tous les attributs d’une classe doivent toujours être privés ! !

On ne peut (doit) pas modifier les attributs depuis l’extérieur de la classe

Prérequis pour cette partie :

Langage JAVA - POO

Page 14: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 14 / 33

d. Séparation des prototypes et des implémentations

Ce n’est pas une obligation mais vivement conseillé car cela permet d’avoir un code

modulaire et plus lisible. On sépare donc la fonction main() du fichier main.cpp des classes.

Pour chaque classe, on créera : o Un header (fichier *.h) qui contiendra les attributs et les prototypes de la classe

o Un fichier source (fichier *.cpp) qui contiendra la définition des méthodes et leur implémentation

Exemple :

Joueur.h

Joueur.cpp

main.cpp

#ifndef DEF_H_JOUEUR

#define DEF_H_JOUEUR

#include <string>

class Joueur

{

private:

int niveauVie ; // niveau de vie du joueur

int niveauMagie ; // niveau de magie

std::string armeJoueur ; // arme du joueur

int puissanceArme ; // puissance de l’arme

public:

void diminuerVie (int vieEnMoins) ;

void augmenterVie (int vieEnPlus) ;

void attaquer (Joueur &cible) ;

void changerArme (std::string nomNouvelleArme,

int puissanceNouvelleArme) ;

bool estVivant() ;

} ;

#endif

#include "Joueur.h"

using namespace std ;

void Joueur::diminuerVie (int vieEnMoins) {

niveauVie -= vieEnMoins ;

if (niveauVie < 0) niveauVie = 0 ;

}

void Joueur::augmenterVie (int vieEnPlus) {

niveauVie += vieEnPlus;

if (niveauVie > 100) niveauVie = 100 ;

}

void Joueur::attaquer (Joueur &cible) {

cible.diminuerVie(puissanceArme) ;

}

void Joueur::changerArme (string

nomNouvelleArme,int puissanceNouvelleArme) {

armeJoueur = nomNouvelleArme ;

puissanceArme = puissanceNouvelleArme ;

}

bool Joueur::estVivant {

return (niveauVie>0) ;

}

#include <iostream>

#include "Joueur.h"

using namespace std ;

int main()

{

Joueur arkonovi,forceBleue ; // creation de deux objets de type Joueur

Joueur forceRouge ; // creation joueur

Joueur forceJauneDevantMarronDerriere ; // creation joueur

arkonovi.attaquer(forceBleue ) ; // arkonovi attaque forceBleue

forceBleue.augmenterVie(20) ; // forceBleue augemente sa vie de 20 pts

arkonovi.attaquer(forceBleue ) ; // arkonovi attaque forceBleue

forceRouge.attaquer(arkonovi) ; // forceRouge défend forcebleue

forceBleue.changerArme("rayon laser bx 4000",40) ; // force bleue change d’arme

arkonovi.attaquer(forceJaune) ; // arkonovi attaque forceJaune

forceRouge.changerArme("rayon laser bx 6000",60) ; // force rouge change d’arme

forceRouge.attaquer(arkonovi) ; // forceJaune contre-attaque

}

Arkonowi : « Ah, je vais vous transformer en bouillie radioactive tellement

liquide qu'on pourra même plus vous manger avec des baguettes ! »

...

Arkonowi : Tiens, prends ça dans ta g euaahhh ! C'est un venin

intersidéral qui te transformera en poudre thermospasmique et qui te fera

des taches sur les habits que même Skip machine pourra pas les enlever !

Page 15: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 15 / 33

e. Constructeur, surcharge du constructeur, constructeur de copie

Constructeur :

Le constructeur une méthode appelée automatiquement à chaque fois que l’on crée un

objet basé sur cette classe.

Un constructeur par défaut est automatiquement créé par le compilateur. Il est vide et ne

fait rien de particulier.

On peut alors créer son constructeur qui remplace le constructeur vide par défaut. Son

principal rôle sera généralement d’initialiser les attributs qui n’ont pas de valeur par

défaut.

Le constructeur est une méthode respectant les deux règles :

o Il porte le même nom que la classe

o La méthode ne doit RIEN renvoyer (même pas void) : c’est une méthode sans aucun type de retour

Exemple : pour la classe Joueur, le constructeur par défaut s’écrira Joueur();

Surcharge du constructeur :

Il est possible de surcharger le constructeur en réécrivant une (ou plusieurs) autre(s)

méthode(s) mais respectant les règles suivantes :

o La surcharge du constructeur porte le même nom que la classe

o Il y a un nombre de paramètres différents,

o S’il y a le même nombre de paramètres, ceux-ci diffèrent d’au moins un type

Exemple : pour la classe Joueur :

- le constructeur par défaut s’écrira : Joueur();

- un autre constructeur peut s’écrire : Joueur(std::string P_armeJoueur , int P_puissanceArme)

- un autre constructeur peut s’écrire : Joueur(std::string P_armeJoueur , int P_puissanceArme, int NiveauVie)

Constructeur de copie

// le constructeur par défaut est appliqué à buzz

// on donne ici une « meilleure arme à woody » avec l’autre constructeur

Joueur buzz, woody("Lance flamme",25) ;

// creation du joueur « david » en copiant les attribut de « woody »

Joueur david(woody) ;

Exemple :

Page 16: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 16 / 33

#ifndef JOUEUR_H_INCLUDED Joueur.h

#define JOUEUR_H_INCLUDED

class Joueur {

private:

int niveauVie ;

int niveauMagie ;

std::string nomJoueur ;

std::string armeJoueur = "Pistolet a eau" ;

int puissanceArme = 10 ;

public:

Joueur();

Joueur(int nV,int nM,int pA,std::string nJ,std::string aJ);

void afficher(void);

};

#endif // JOUEUR_H_INCLUDED

#include <iostream> Joueur.cpp

#include "joueur.h"

// constructeur par defaut

Joueur::Joueur(){

niveauVie = 50 ;

niveauMagie = 0 ;

nomJoueur = "inconnu" ;

}

// surcharge constructeur

Joueur::Joueur(int nV,int nM,int pA,std::string nJ,std::string aJ) {

niveauVie = nV ;

niveauMagie = nM ;

nomJoueur = nJ ;

armeJoueur = aJ ;

puissanceArme = pA ;

}

// afficher

void Joueur::afficher() {

std::cout << "Nom : " << nomJoueur << std::endl ;

std::cout << "Arme : " << armeJoueur << " ("<< puissanceArme << ")"<< std::endl ;

std::cout << "Vie : " << niveauVie << std::endl ;

std::cout << "Magie: " << niveauMagie << std::endl <<std::endl ;

}

Fichier

#include <iostream> main.cpp

#include "Joueur.h"

using namespace std;

int main() {

Joueur joueur1;

Joueur joueur2(100,0,30,"Feroce","Char FOCH");

joueur1.afficher();

joueur2.afficher();

return 0;

}

La liste d’initialisation : autre moyen pour initialiser avec un constructeur

Joueur::Joueur():niveauVie(100),niveauMagie(100),armeJoueur("Pistolet à eau"),puissanceArme(10)

{

// rien à mettre ici... Tout a déjà été fait !

}

L’implémentation dans « Joueur.cpp » sera :

Joueur::Joueur(string aJ, int pA):

niveauVie(100),niveauMagie(100),armeJoueur(aJ),puissanceArme(pA)

Remarque : le prototype ne change pas dans le fichier « Joueur.h »

Page 17: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 17 / 33

f. Destructeur

C’est une méthode appelée automatiquement lorsqu’un objet est détruit.

Son principal rôle est de « désallouer » la mémoire qui a été allouée

dynamiquement.

Ici, le cas de notre classe Joueur, on n'a fait aucune allocation dynamique (il n'y a aucun

new). Le destructeur est donc inutile.

On en a besoin quand on est amené à faire des allocations dynamiques.

Un destructeur est une méthode qui commence par un tilde (~) suivi du nom de la classe.

Un destructeur ne renvoie aucune valeur, pas même void (comme le constructeur).

Le destructeur ne prendre aucun paramètre. Il n’y a donc qu’un seul destructeur,

Fichier Joueur.h (prototype)

class Joueur

{

public:

~Joueur() ; // destructeur

...

} ;

Fichier Joueur.cpp (implémentation)

Joueur::~Joueur()

{

// rien ICI

}

g. Les méthodes constantes

o Ce sont des méthodes en lecture seule

o Elles possèdent le mot-clé « const » à la fin de leur prototype et de leur déclaration

o La méthode ne modifie pas l’objet (aucune valeur d’attribut modifié)

o Ce sont généralement des méthodes qui se contentent de renvoyer des infos sans modification

// Prototype de la méthode (dans le fichier Joueur.h)

bool estVivant() const ;

// Implémentation de la méthode (dans le fichier Joueur.cpp)

bool Joueur::estVivant() const

{

return (niveauVie>0) ;

}

h. Multiplier les classes et les associer entre-elles

En reprenant l’exemple précédent,

créons une classe « arme » et les

deux fichiers de définition et

d’implémentation : « arme.h » et

« arme.cpp »

Voir les fichiers page suivante

Résultat de l’exécution ci-contre :

Page 18: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 18 / 33

Arme.h

Arme.cpp

Il est alors nécessaire de modifier la classe Joueur pour qu’elle utilise l’objet Arme

Joueur.cpp

Joueur.h

main.cpp

#ifndef ARME_H_INCLUDED

#define ARME_H_INCLUDED

#include<iostream>

#include<string>

class Arme

{

private :

std::string nom ; // arme du joueur

int puissance ; // puissance de l’arme

public:

Arme() ; //constructeur par défaut

Arme(std::string pNom,int pPuissance) ;

void changerArme(std::string pNom,int pPuissance) ;

void afficher() const ;

int getPuissance() const ; // getter

} ;

#endif

#include "Arme.h"

using namespace std ;

Arme::Arme() : nom("couteau"),puissance(5) { }

Arme::Arme(string pNom,int pPuissance) : nom(pNom), puissance(pPuissance) { }

void Arme::changerArme(string pNom,int pPuissance)

{

nom = pNom ;

puissance = pPuissance ;

}

void Arme::afficher() const

{

cout << "Arme : " << nom << " (Puissance : " << puissance << ")" << endl ;

}

int Arme::getPuissance() const

{

return puissance ;

}

#include "Joueur.h"

using namespace std ;

void Joueur::diminuerVie (int vieEnMoins)

{

niveauVie -= vieEnMoins ;

if (niveauVie < 0)

niveauVie = 0 ;

}

void Joueur::augmenterVie (int vieEnPlus)

{

niveauVie += vieEnPlus;

if (niveauVie > 100)

niveauVie = 100 ;

}

void Joueur::attaquer (Joueur &cible)

{

cout << nomJoueur << " attaque " << cible.nomJoueur ;

cout << endl ;

cible.diminuerVie(jArme.getPuissance()) ;

}

void Joueur::changerArme (string nomNouvelleArme,

int puissanceNouvelleArme)

{

jArme.changerArme(nomNouvelleArme,puissanceNouvelleArme) ;

}

bool Joueur::estVivant () const

{

return (niveauVie>0) ;

}

Joueur::Joueur(): niveauVie(0),

niveauMagie(0),

nomJoueur("inconnu") {}

Joueur::Joueur(string pNomJoueur) : niveauVie(50),

niveauMagie(50),

nomJoueur(pNomJoueur){}

Joueur::Joueur(string pNomJoueur,string pArme,int pPuissance)

{

niveauVie = 100 ;

niveauMagie = 100 ;

nomJoueur = pNomJoueur ;

jArme = Arme(pArme,pPuissance) ;

}

void Joueur::afficher() const

{

cout << "Joueur: " << nomJoueur ;

cout << "\tVie: " << niveauVie ;

cout << "\tMagie: " << niveauMagie ;

jArme.afficher() ;

}

#ifndef DEF_H_JOUEUR

#define DEF_H_JOUEUR

#include<iostream>

#include<string>

#include "Arme.h" // NE PAS OUBLIER

class Joueur

{

private:

int niveauVie ; // niveau de vie du joueur

int niveauMagie ; // niveau de magie du joueur

std::string nomJoueur ; // nom du joueur

Arme jArme ; // le joueur possède une arme

public:

Joueur();

Joueur(std::string pNomJoueur) ;

Joueur(std::string pNomJoueur, std::string pArme,

int pPuissance) ;

void diminuerVie (int vieEnMoins) ;

void augmenterVie (int vieEnPlus) ;

void attaquer (Joueur &cible) ;

void changerArme (std::string nomNouvelleArme,

int puissanceNouvelleArme) ;

bool estVivant() const ;

void afficher() const ;

} ;

#endif

#include <iostream>

#include "Joueur.h"

using namespace std ;

int main()

{

Joueur arkonovi("arkonovi","bazouka",40);

Joueur forceBleue("force bleue","Famas",35);

Joueur forceRouge("force rouge") ;

Joueur forceJauneDevantMarronDerriere ;

cout << " ******* AVANT *******" << endl ;

arkonovi.afficher() ;

forceRouge.afficher() ;

forceJauneDevantMarronDerriere.afficher() ;

forceBleue.afficher() ;

cout << endl << "****** COMBAT A MORT *****" << endl ;

arkonovi.attaquer(forceBleue) ;

forceBleue.augmenterVie(20) ;

arkonovi.attaquer(forceBleue) ;

forceRouge.attaquer(arkonovi) ;

forceBleue.changerArme("rayon laser bx 4000",40) ;

arkonovi.attaquer(forceRouge);

forceRouge.changerArme("rayon laser bx 6000",60) ;

forceRouge.attaquer(arkonovi) ;

cout <<endl << " ******* APRES *******" << endl ;

arkonovi.afficher() ;

forceRouge.afficher() ;

forceJauneDevantMarronDerriere.afficher() ;

forceBleue.afficher() ;

}

Page 19: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 19 / 33

2. La surcharge d’opérateurs

Réalisation d’opérations mathématiques (+,-,*,==,>,…) entre les objets

Exemple :

duree.h

duree.cpp

main.cpp

On pourrait écrire une fonction qui fait :

Total = addition(d1,d2) ;

L’objectif ici est de pouvoir faire directement:

Total = d1 + d2 ;

Ou toute autre opération du genre :

if ( d1 == d2) cout << " durées identiques" ;

if (d1 < d2) cout << "d1 plus petit que d2" ;

Solution :

Créer une fonction (en dehors de toute classe) ayant pour nom operator suivi de l’opérateur à

implémenter.

Exemple de prototype pour == : bool operator== (Duree const& a, Duree const& b) ;

Exemple de prototype pour + : Duree operator+ (Duree const& a, Duree const& b) ;

Exemple de prototype pour != : bool operator != (Duree const& a, Duree const& b) ;

Implémentation incorrecte :

bool operator== (Duree const& a, Duree const& b)

{

if ( (a.heure==b.heure) && (a.minute==b.minute) &&(a.seconde==b.seconde) )

return true ;

else

return false ;

}

On ne peut pas lire les attributs des objets a et b :

Ils sont privés et donc inaccessibles depuis l’extérieur de la classe.

Solution : créer des accesseurs aux variables membres (ie getters) :

getHeures(), getMinutes(),getSecondes()

Implémentation correcte :

bool operator== (Duree const& a, Duree const& b) {

if ( (a.getHeure()==b.getHeure()) && (a.getMinute()==b.getMinute())

&&(a.getSeconde()==b.getSeconde()) )

return true ;

else

return false ;

}

#ifndef DUREE_H_INCLUDED

#define DUREE_H_INCLUDED

class Duree

{

private :

int heure ;

int minute ;

int seconde ;

public:

// Constructeur avec valeurs par defaut

Duree(int pHeure=0,int pMinutes=0,int pSeconde=0) ;

} ;

#endif

#include "Duree.h"

Duree::Duree(int pHeure,int pMinutes,int pSeconde) :

heure(pHeure),minute(pMinute),seconde(pPseconde)

{

}

#include "Duree.h"

int main()

{

Duree Total ;

Duree d1(0,15,30) ;

Duree d2(1,10) ;

...

return 0 ;

}

Page 20: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 20 / 33

Autre solution : Créer une méthode de la classe qui accède aux attributs privés sans passer

les accesseurs (ie getters). On crée alors une méthode dans la classe qui fait la comparaison et

on demande à l’opérateur d’appeler cette fonction

Implémentation de la méthode estEgal

bool Duree::estEgal (Duree const& d) const

{

if ( (heure==d.heure) && (minute==d.minute) && (seconde==d.seconde) )

return true ;

else

return false ;

}

Création de la fonction operateur== qui utilise la méthode estEgal

bool operator== (Duree const& a, Duree const& b)

{

return ( a.estEgal(b) ) ;

}

Dans le main(), on peut maintenant écrire :

int main()

{

Duree d1(0,5,30), d2(0,6,30) ;

if (d1 == d2)

cout << "les durées sont identiques" ;

else

cout << "les durées sont différentes" ;

}

Remarque sur l’implémentation de la fonction :

Pour être sûr que la comparaison fonctionne comme dans le cas suivant Duree d1(1,5,30), d2(1,4,180) ;

Il faudrait convertir les durées (h,min,s) en seconde et effectuer la comparaison

sur les secondes

Pour vous entrainer,

Créer les opérateurs suivant :

bool operator!= (Duree const& a, Duree const& b) ;

bool operator< (Duree const& a, Duree const& b) ;

Duree operator+ (Duree const& a, Duree const& b) ;

void operator+= (Duree const& d) ;

Si l’envie vous démange, poussez alors votre curiosité pour savoir faire :

int main()

{

Duree d1(0,5,30), d2(0,6,30), d3(1,0,50) ;

Duree total1, total2 ;

total1 = d1 + d2 + d3 ; // comment faire ?????

total2 = d1 + 30 ; // comment faire ?????

}

Page 21: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 21 / 33

3. L’héritage

a. Création d’une classe et d’un héritage

C’est créer une classe à partir d’une autre classe

Dans notre exemple précédent, on peut dire que « un

gentil est un joueur » ou « un méchant est un joueur ».

Ce qui permet de définir l’héritage :

La classe Gentil herite de Joueur

la classe Mechant herite de Joueur

En reprenant l’exemple traité précédemment,

Joueur.h

Joueur.cpp

La classe Mechant hérite de Joueur :

La classe Joueur est appelée classe « mère »

La classe Mechant est appelée classe « fille »

La classe Mechant contiendra tous les attributs et toutes les méthodes de la classe Joueur

Il est alors possible d’ajouter des attributs et des méthodes spéciales dans la classe Mechant

Mechant.h

On peut faire la même chose pour la classe Gentil :

Gentil.h

#ifndef DEF_H_JOUEUR

#define DEF_H_JOUEUR

#include<iostream>

#include<string>

class Joueur

{

private:

int niveauVie ; // niveau de vie du joueur

std::string nomJoueur ; // nom du joueur

public:

Joueur();

void souffrir (int vieEnMoins) ;

void attaquer (Joueur &cible) const ;

} ;

#endif

#include "Joueur.h"

Using namespace std ;

Joueur::Joueur() : niveauVie(100), nomJoueur("Inconnu")

{

}

void Joueur::souffrir(int vieEnMoins)

{

niveauVie -= vieEnMoins ;

}

void Joueur::attaquer(Joueur &cible) const

{

cible.souffrir(5) ;

}

#ifndef DEF_H_MECHANT

#define DEF_H_MECHANT

#include<iostream>

#include<string>

#include "Joueur.h" // A inclure pour pouvoir en hériter !

class Mechant : public Joueur

{

public:

void frapperCommeUneBruteSansCervelle() const ;

} ;

#endif

#ifndef DEF_H_GENTIL

#define DEF_H_GENTIL

#include<iostream>

#include<string>

#include "Joueur.h" // A inclure pour pouvoir en hériter !

class Gentil : public Joueur

{

private :

int pouvoirTelekinesie ;

public:

void ushiroGeri() const ;

void mawashiGeri() const ;

} ;

#endif

Joueur

Gentil

Mechant

Page 22: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 22 / 33

b. La dérivation de type

Exemple d’utilisation :

Joueur rocEtGravillon ;

Mechant satanasEtDiabolo ;

rocEtGravillon.attaquer(satanasEtDiabolo) ;

satanasEtDiabolo.attaquer(rocEtGravillon) ;

L’instruction satanasEtDiabolo.attaquer(rocEtGravillon); envoie un Joueur en paramètre.

L’instruction rocEtGravillon.attaquer(satanasEtDiabolo) ;

est fonctionnelle également même si on lui transmet un Mechant (objet fille)

C'est une propriété de l'héritage en C++ : la méthode attaquer peut être utilisée sur n’importe quel

joueur (objet mère), qu’il soit Mechant ou Gentil (objet fille)

c. Constructeur

Constructeur par défaut (mère) : Joueur(); // défini dans joueur.h

Implémentation dans joueur.cpp :

Joueur::Joueur() : niveauVie(100), nomJoueur("Inconnu") {}

Lors de la création de l’objet (mère), le constructeur est appelé en premier

Lors de la création de l’objet (fille), voici ce qu’il se produit : o Le compilateur appelle d'abord le constructeur de la classe mère (Joueur) ;

o Le compilateur appelle ensuite le constructeur de la classe fille (Mechant).

Pour initialiser le constructeur de la classe fille, on écrit :

Gentil::Gentil() : Joueur(), pouvoirTelekinesie (1000) { }

Le 1er élément de la liste d'initialisation fait appel d’abord au constructeur de la classe

parente Joueur puis on effectue les initialisations propres à l’objet fille Gentil

Transmission de paramètres :

Gentil::Gentil(string nomJ ) : Joueur(nomJ), pouvoirTelekinesie (1000) { }

d. La portée « protected »

Rappel :

La portée « public » : les éléments qui suivent sont accessibles depuis l'extérieur de la

classe

La portée « private » : les éléments qui suivent ne sont pas accessibles depuis l'extérieur

de la classe.

L’encapsulation empêche systématiquement depuis l’extérieur d'accéder aux attributs des

classes.

La portée « protected » est un autre type de droit d'accès qui n'a de sens que pour les classes qui

se font hériter (les classes mères).

Page 23: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 23 / 33

Les éléments qui suivent « protected » ne sont pas accessibles depuis l'extérieur de la classe, sauf

si c'est une classe fille ; ce qui n’est pas le cas avec la portée « private »

e. Le masquage

Quand on fait un héritage, la classe fille reçoit automatiquement toutes les méthodes de la classe

mère. Si une de ces méthodes ne convient pas, on la réécrit dans la classe fille. Quand on écrit une

fonction qui a le même nom que celle héritée de la classe mère, on parle de masquage. La fonction

héritée de Joueur est masquée.

Classe mère

void Joueur::sePresenter() const

{

cout << "Bonjour, je m'appelle " << nomJoueur << endl;

cout << "J'ai " << niveauVie << " points de niveau de vie." << endl;

}

La fonction est héritée dans la classe fille (Mechant). On peut donc écrire :

int main(){

Mechant Mechant1("Arkanovi");

Mechant1.sePresenter();

return 0;

}

On peut écrire une fonction spéciale de présentation pour les Mechant :

void Mechant::sePresenter() const

{

cout << "Bonjour, je m'appelle " << nomJoueur << endl;

cout << "J'ai "<< niveauVie << " points de niveau de vie." << endl;

cout << "Je suis le mechant et je veux tuer la gentille." << endl;

}

f. Le démasquage

void Mechant::sePresenter() const

{

Joueur::sePresenter();

cout << "Je suis le mechant et je veux tuer la gentille." << endl;

}

Dans cet exemple, la fonction sePrésenter du méchant ne fait que compléter la fonction de la

classe Mère. Pour éviter de recopier ce que fait déjà la classe mère, on démasque alors la fonction

en l’appelant dans la classe fille. On complète ensuite avec ce que l’on souhaite faire.

On parle dans ce cas de démasquage puisqu'on a utilisé une fonction qui était masquée.

On a utilisé pour cela l'opérateur de résolution de portée :: qui a servi à déterminer quelle

fonction utiliser quand il y a ambiguïté ou s’il y a plusieurs possibilités.

Page 24: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 24 / 33

4. Le polymorphisme

a. Constat

On reprend la notion d’héritage ci-dessus et on ajoute une méthode permettant l’affichage :

void Joueur::affiche() const {

cout << "Je suis un joueur." << endl;

}

void Gentil::affiche() const {

cout << "je suis un gentil." << endl;

}

void Mechant::affiche() const {

cout << "je suis un méchant." << endl;

}

On affiche sans problème les messages différents en utilisant le masquage :

int main()

{

Joueur j ;

j.affiche(); // affiche « Je suis un joueur. »

Gentil g ;

g.affiche(); // affiche « je suis un gentil »

}

Nous allons une fonction supplémentaire qui

reçoit en paramètre un Joueur.

On modifie le main() de la façon suivante :

void presenter(Joueur pJ)

{

pJ.affiche() ;

}

int main()

{

Joueur j ;

presenter(j);

Mechant m ;

presenter(m);

}

Le résultat de l’affichage est sans appel !

On pouvait s’en douter !

Lors de l’appel de la fonction, la nature

cruelle du méchant s’est perdue et est

redevenue un joueur

On parle ici de résolution statique de lien : la

fonction presenter() reçoit un Joueur : c’est

donc toujours la « version Joueur » des

méthodes qui sera utilisée

On aimerait bien que la

bonne méthode soit appelée

en reconnaissant la nature du Joueur !

La fonction presenter() doit appeler la bonne version de la méthode : elle doit connaitre la vraie

nature du Joueur : C'est ce qu'on appelle la résolution dynamique des liens.

Lorsque le programme s’exécute, il utilise la bonne version des méthodes car il sait si l'objet est de

type mère ou de type fille. Pour faire cela, il faut :

utiliser des méthodes virtuelles.

utiliser un pointeur (ou une référence)

Je suis un joueur.

Je suis un joueur.

Page 25: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 25 / 33

a. Déclaration d’une méthode virtuelle

Il suffit d'ajouter le mot-clé virtual uniquement dans le prototype de la classe (fichier .h et pas

dans le fichier .cpp)

class Joueur {

public:

virtual void affiche() const; // Affiche une description du Joueur

};

class Gentil: public Joueur {

public:

virtual void affiche() const;

};

class Mechant : public Joueur {

public:

virtual void affiche() const;

};

Remarque :

Il n'est pas nécessaire de mettre le mot clé « virtual » devant les méthodes des classes filles. Elles

sont automatiquement virtuelles par héritage.

b. Utilisation d’une référence

Il est nécessaire de modifier la fonction presenter() avec un passage par référence pour les

paramètres :

void presenter(Joueur& pJ)

{

pJ.affiche() ;

}

int main()

{

Joueur j ;

presenter(j);

Mechant m ;

presenter(m);

}

Le résultat devient correct

Ouf !

La fonction presenter() a appelé la bonne

version de la méthode.

___________________________

Pour aller plus loin en C++ :

- La gestion des erreurs avec les exceptions : try{…} , throw, catch() {…}

- L’héritage multiple

- Les pointeurs et les collections (tableaux contenant des types différents)

La bibliothèque Qt, version actuelle 5.5 : bibliothèque externe indépendante

permet de créer vos propres fenêtres sous Windows, Linux ou Mac OS

(bibliothèque graphique multiplateforme) : ouverture de fenêtres, ajout de

boutons, création de menus, de listes déroulantes...

Je suis un joueur.

Je suis un méchant.

Page 26: Prérequis : - Langage C - Java / POO · 2017-12-15 · Langage développé par Bjarne STROUSTRUP (années 80) Evolution du langage C avec l’apport de la POO Langage de programmation

D. DUBOIS Version 3 – Mars 2016 Page 26 / 33

XI. Exercices

1. Exercice 1 : trier/échanger

Créez une fonction "trier" permettant de trier un tableau de 10 données avec un tri par sélection.

Le tableau devra être de n'importe quel type. Cette fonction utilisera une autre fonction qu’on nommera "echanger" qui

échangera les éléments du tableau. Les 10 données seront générées de manière aléatoire. Le Tri par sélection est décrit

par la procédure suivante :

1. Rechercher le plus petit élément du tableau et l'échanger avec l'élément d'indice 1

2. Rechercher le second plus petit élément du tableau, et l'échanger avec l'élément d'indice 2

3. Et ainsi de suite jusqu'à ce que le tableau soit entièrement trié.

2. Exercice 2 : Référence

Ecrire une fonction f ayant en paramètres un tableau t de taille quelconque et un entier n indiquant la taille du tableau. f

possède un autre paramètre v entier passé par référence.

f doit renvoyer un booléen b indiquant s'il existe une valeur comprise entre 1 et 10 dans les n premières cases du tableau t.

Si f renvoie true, v est égal à la valeur de la première case du tableau comprise entre 0 et 10

3. Exercice 3 : Recopie

Ecrire une fonction f ayant en paramètres un tableau t1 de taille quelconque et un entier n indiquant la taille du tableau,

ainsi qu'un tableau t2 de la même taille que t1. f doit renvoyer un entier nb indiquant le nombre de valeurs comprises

entre 0 et 10 dans le tableau t1. f doit mettre dans le tableau t2 les différentes valeurs comprise entre 0 et 10 qu'il a

rencontrées dans le tableau t1.

4. Exercice 4 : String

Ecrire un programme qui saisit une chaîne pouvant contenir des espaces et qui affiche chaque mot

de la chaîne, le séparateur étant l'espace. Exemple, on tape : je pense donc je suis

5. Exercice 5 : Classe

On souhaite implémenter une classe représentant un compteur entier. Un tel objet se caractérise par :

Une valeur entière, positive ou nulle, nulle à l'origine. Le fait qu'il ne peut varier que par pas de 1 (incrémentation ou

décrémentation). On convient qu'une décrémentation d'un compteur nul est sans effet. Il s'agit de créer une classe

Compteur pour rendre le service demandé. On écrira en outre un petit programme de test qui :

1. créera un compteur et affichera sa valeur

2. l'incrémentera 10 fois, puis affichera à nouveau sa valeur

3. le décrémentera 20 fois, puis affichera une troisième fois sa valeur

La sortie de ce programme doit donner (quelque chose comme) "0 10 0"

6. Exercice 6 : classe

Réaliser une classe point permettant de manipuler un point d'un plan. On prévoira :

- un point est définit par ses coordonnées x et y (des membres privés)

- un constructeur ou plusieurs constructeurs

- une fonction membre déplace effectuant une translation définie par ses deux arguments dx et dy

- une fonction membre affiche se contentant d'afficher les coordonnées cartésiennes du point.

- une fonction membre saisir se contentant de saisir les coordonnées cartésiennes du point.

- une fonction membre distance effectuant calculant la distance entre deux points.

- une fonction membre milieu donnant le milieu d'un segment.

On écrira séparément :

- un fichier source constituant la déclaration et la définition de la classe.

- un programme d’essai (main) gérant ne la classe point.

7. Exercice 7 : surcharge d’opérateurs

En reprenant les éléments du cours, compléter le programme ci-dessous en surchargeant les opérateurs ==, != et < pour

que le programme fonctionne

int main() {

Duree duree1(0, 10, 28), duree2(0, 10, 29);

if (duree1 == duree2) cout << "Les durees sont identiques";

if (duree1 != duree2) cout << "Les durees sont differentes";

if (duree1 < duree2) cout << "La premiere duree est plus petite";

else cout << "La premiere duree n'est pas plus petite";

return 0 ;

}