Vous êtes sur la page 1sur 230

C++ : programmation orientée-objet

Achref El Mouelhi

Docteur de l’université d’Aix-Marseille


Chercheur en programmation par contrainte (IA)
Ingénieur en génie logiciel

elmouelhi.achref@gmail.com

Avril 2018 1 / 124


Plan
1 Rappel
2 Classe
Setter
Getter
Constructeur
Constructeur de copie
Constructeur de conversion
Destructeur
Attributs et méthodes statiques
Fonction amie
Fonction inline
Opérateur de conversion
3 Association simple entre classes
Association simple sans pointeur
Association simple avec pointeur

Avril 2018 2 / 124


Plan
4 Héritage
Héritage simple
Héritage multiple
Mode de visibilité
5 Polymorphisme
Surcharge
Redéfinition
Méthode virtuelle
Méthode virtuelle pure
6 Classe abstraite
7 Interface
8 Opérateur
9 Énumération
10 struct
Avril 2018 3 / 124
Rappel

C++
Qu’est ce qu’une classe en POO ?

Ça correspond à un plan, un moule, une usine...


C’est une description abstraite d’un type d’objets
I c
E
Elle représente un ensemble d’objets ayant lesH
L mêmes propriétés
statiques (attributs) et dynamiques O U
L M (méthodes)
h r e fE
A c
c

Avril 2018 4 / 124


Rappel

C++
Qu’est ce qu’une classe en POO ?

Ça correspond à un plan, un moule, une usine...


C’est une description abstraite d’un type d’objets
I c
E
Elle représente un ensemble d’objets ayant lesH
L mêmes propriétés
statiques (attributs) et dynamiques O U
L M (méthodes)
r e E
f d’instance
Qu’est ce que c’est lah
A c notion ?
c correspond à un objet créé à partir d’une classe (via
Une instance
le constructeur)
L’instanciation : création d’un objet d’une classe
instance ≡ objet

Avril 2018 4 / 124


Rappel

C++

De quoi est composé une classe ?

NomClasse

I c

les attributs
ELH
U
L MO
r e f E
les méthodes

c h
c A

Attribut : [visibilité] + type + nom
Méthode : [visibilité] + valeur de retour + nom + arguments ≡
signature : exactement comme les fonctions en procédurale

Avril 2018 5 / 124


Classe

C++
Particularité du C++ et bonnes pratiques

Garder la fonction principale dans un fichier séparé

I c
Définir la structure de la classe dans un fichier .h portant le nom de la

classe et l’implémentation dans un fichier .cpp
EL H
U
L MO
Le mot-clé this permet de désigner l’objet courant.

h r e fE
A c
c

Avril 2018 6 / 124


Classe

C++
Particularité du C++ et bonnes pratiques

Garder la fonction principale dans un fichier séparé

I c
Définir la structure de la classe dans un fichier .h portant le nom de la

classe et l’implémentation dans un fichier .cpp
EL H
U
L MO
Le mot-clé this permet de désigner l’objet courant.

Créons deux classes hre


fE
A c
c
Créons
deux fichiers File > New > File : le premier
Personne.cpp et le deuxième Personne.h

Les attributs de la classe Personne : num, nom, prénom et genre

Une seule méthode : afficherDetails()

Avril 2018 6 / 124


Classe

Contenu de Personne.h

#ifndef PERSONNE_H_INCLUDED
#define PERSONNE_H_INCLUDED

using namespace std;

class Personne {
public : void afficherDetails() const;
I c

public : int num;
ELH
public : string nom;
U
public : string prenom;
L MO
public : char genre;
f E
hre
};

c
#endif // PERSONNE_H_INCLUDED

c A

Avril 2018 7 / 124


Classe

Contenu de Personne.h

#ifndef PERSONNE_H_INCLUDED
#define PERSONNE_H_INCLUDED

using namespace std;

class Personne {
public : void afficherDetails() const;
I c

public : int num;
ELH
public : string nom;
U
public : string prenom;
L MO
public : char genre;
f E
hre
};
#endif // PERSONNE_H_INCLUDED
c
Remarques
c A

Par défaut, la visibilité des attributs et méthodes, en C++, est private.

Les attributs ne seront donc pas accessibles depuis l’extérieur, il faut les déclarer public.

Le mot clé const indique au compilateur que la méthode ne modifie pas l’objet.

Avril 2018 7 / 124


Classe

C++
Le code précédent peut-être factorisé (en supprimant les public répétés)

#ifndef PERSONNE_H_INCLUDED
#define PERSONNE_H_INCLUDED

class Personne
I c

{
ELH
U
MO
public :
void afficherDetails() const;

f E L
public :
c hre
c A
int num;

string nom;
string prenom;
char genre;
};

#endif // PERSONNE_H_INCLUDED

Avril 2018 8 / 124


Classe

C++

I c

Dans Personne.cpp
LH
Faire clic droit sur le panneau central UE
M O
f
Aller dans Insert puis choisirL
E All class methods without
implementation...
ch r e
c A

Avril 2018 9 / 124


Classe

C++
Code généré de Personne.cpp

void Personne::afficherDetails() const


{
}

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 10 / 124


Classe

C++
Code généré de Personne.cpp

void Personne::afficherDetails() const


{
}

I c

ELH
Modifions ce contenu pour qu’il soit ainsi U
L MO
fE
#include <iostream>
#include "Personne.h"
c h r e
using namespaceA
c std;

void Personne::afficherDetails() const


{
cout << num << " " << prenom << " ";
cout << nom << " " << genre << endl;
}

Avril 2018 10 / 124


Classe

C++

Pour instancier (créer un objet de) la classe : deux solutions


sans pointeur :
I c
H
déclarer une variable (comme toute autre variable) de type
EL
Personne
U
MOen utilisant l’opérateur .
affecter des valeurs à ses attributs
L
avec pointeur :
h r e fE
déclarerA
c
c un pointeur sur Personne
utiliser l’opérateur new + nom de la classe pour le créer
dynamiquement
affecter des valeurs à ses attributs en utilisant l’opérateur ->

Avril 2018 11 / 124


Classe

C++
Déclarons un objet de la classe Personne, comme une variable, dans le main
#include <iostream>
#include "Personne.h"
using namespace std;

I c

int main()
{
ELH
U
MO
Personne personne;
}
f E L
c hre
c A

Avril 2018 12 / 124


Classe

C++
Déclarons un objet de la classe Personne, comme une variable, dans le main
#include <iostream>
#include "Personne.h"
using namespace std;

I c

int main()
{
ELH
U
MO
Personne personne;
}
f E L
A c hre
Pour affecter une valeur à un attribut
c
= "wick";
personne.nom

Avril 2018 12 / 124


Classe

C++
Déclarons un objet de la classe Personne, comme une variable, dans le main
#include <iostream>
#include "Personne.h"
using namespace std;

I c

int main()
{
ELH
U
MO
Personne personne;
}
f E L
A c hre
Pour affecter une valeur à un attribut
c
= "wick";
personne.nom

Pour les autres attributs


personne.prenom = "john";
personne.genre = ’M’;
personne.num = 100;
Avril 2018 12 / 124
Classe

C++

I c

Pour appeler une méthode
E LH
personne.afficherDetails(); OU
L M
ref E
// affiche 100 john wick M

c h
c A

Avril 2018 13 / 124


Classe

C++

Deuxième solution : déclarons un pointeur de la classe Personne


Personne *personne;

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 14 / 124


Classe

C++

Deuxième solution : déclarons un pointeur de la classe Personne


Personne *personne;

I c

E LH
U
MO new
Pour créer l’objet, il faut utiliser l’opérateur
L
personne = new Personne();
h r e fE
A c
c

Avril 2018 14 / 124


Classe

C++

Deuxième solution : déclarons un pointeur de la classe Personne


Personne *personne;

I c

E LH
U
MO new
Pour créer l’objet, il faut utiliser l’opérateur
L
personne = new Personne();
h r e fE
A c
c
Les deux étapes précédentes peuvent-être fusionnées
Personne *personne = new Personne();

Avril 2018 14 / 124


Classe

C++

Pour les attributs


personne->nom = "wick";
personne->prenom = "john"; I c

personne->genre = ’M’;
ELH
U
personne->num = 100;
L MO
f E
chre
c A

Avril 2018 15 / 124


Classe

C++

Pour les attributs


personne->nom = "wick";
personne->prenom = "john"; I c

personne->genre = ’M’;
ELH
U
personne->num = 100;
L MO
f E
chre
c A

Pour appeler une méthode
personne->afficherDetails();
// affiche 100 john wick M

Avril 2018 15 / 124


Classe Setter

C++
Hypothèse

Supposant que l’on n’accepte seulement les valeurs M ou F pour l’attribut


genre de la classe Personne

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 16 / 124


Classe Setter

C++
Hypothèse

Supposant que l’on n’accepte seulement les valeurs M ou F pour l’attribut


genre de la classe Personne

I c
Démarche
EL H
U
1

L MO la visibilité à private)
Bloquer l’accès directe aux attributs (mettre

2
e f E qui contrôlent l’affectation de valeurs
Définir des méthodesrpubliques
h
aux attributs (lescsetter)
c A

Avril 2018 16 / 124


Classe Setter

C++
Hypothèse

Supposant que l’on n’accepte seulement les valeurs M ou F pour l’attribut


genre de la classe Personne

I c
Démarche
EL H
U
1

L MO la visibilité à private)
Bloquer l’accès directe aux attributs (mettre

2
e f E qui contrôlent l’affectation de valeurs
Définir des méthodesrpubliques
h
aux attributs (lescsetter)
c A
Convention

Mettre la visibilité private ou protected pour tous les attributs

Mettre la visibilité public pour toutes les méthodes


Avril 2018 16 / 124
Classe Setter

C++
Mettons la visibilité private pour tous les attributs de la classe Personne
#ifndef PERSONNE_H_INCLUDED
#define PERSONNE_H_INCLUDED

#include<string>

class Personne
I c

{
ELH
public :
U
void afficherDetails() const;
L MO
f E
hre
private:
int num;
c
c A
std::string nom;

std::string prenom;
char genre;
};

#endif // PERSONNE_H_INCLUDED

Avril 2018 17 / 124


Classe Setter

C++
Mettons la visibilité private pour tous les attributs de la classe Personne
#ifndef PERSONNE_H_INCLUDED
#define PERSONNE_H_INCLUDED

#include<string>

class Personne
I c

{
ELH
public :
U
void afficherDetails() const;
L MO
f E
hre
private:
int num;
c
c A
std::string nom;

std::string prenom;
char genre;
};

#endif // PERSONNE_H_INCLUDED

Compilation ⇒ erreur
Les attributs sont privés ⇒ inaccessibles.
Avril 2018 17 / 124
Classe Setter

Déclarons les setters dans Personne.h L’implémentation dans Personne.cpp

#ifndef PERSONNE_H_INCLUDED void Personne::setNum(int num)


#define PERSONNE_H_INCLUDED {
this->num = num;
using namespace std; }

class Personne void Personne::setNom(string nom)


{ {
I c

public :
void setNum(int num); }
ELH
this->nom = nom;

U
MO
void setNom(string nom);
void setPrenom(string prenom); void Personne::setPrenom(string

f EL
void setGenre(char genre); prenom)

c h re
void afficherDetails() const; {
this->prenom = prenom;
private:
int num; c
A }

string nom; void Personne::setGenre(char genre)


string prenom; {
char genre; if(genre == ’F’ || genre == ’M’)
}; this->genre = genre;
else
#endif // PERSONNE_H_INCLUDED this->genre = ’M’;
}

Avril 2018 18 / 124


Classe Setter

C++
Utilisons const& dans Personne.h
#ifndef PERSONNE_H_INCLUDED
#define PERSONNE_H_INCLUDED

using namespace std;

class Personne
I c

{
ELH
public :
U
void setNum(int const& num);
L
void setNom(string const& nom); MO
f E
hre
void setPrenom(string const& prenom);

c
void setGenre(char const& genre);

c A
void afficherDetails() const;

private:
int num;
string nom;
string prenom;
char genre;
};

#endif // PERSONNE_H_INCLUDED
Avril 2018 19 / 124
Classe Setter

C++
Adaptons Personne.cpp
void Personne::setNum(int const& num)
{
this->num = num;
}

void Personne::setNom(string const& nom)


I c

{
ELH
this->nom = nom;
U
}
L MO
f E
hre
void Personne::setPrenom(string const& prenom)
{
c
c A
this->prenom = prenom;
}

void Personne::setGenre(char const& genre)
{
if(genre == ’F’ || genre == ’M’)
this->genre = genre;
else
this->genre = ’M’;
}
Avril 2018 20 / 124
Classe Setter

C++

I c

Remarque ELH
U
L
this : pointeur sur l’objet courant MO
f E
c hre
c A

Avril 2018 21 / 124


Classe Setter

C++
Mettons à jour la fonction principale
#include <iostream>
#include "Personne.h"

using namespace std;


I c

int main()
ELH
{ U
Personne personne;
L MO
personne.setNom("wick");
f E
hre
personne.setPrenom("john");
c
c A
personne.setGenre(’M’);

personne.setNum(100);
personne.afficherDetails();
return 0;
}

Avril 2018 22 / 124


Classe Setter

C++
Mettons à jour la fonction principale
#include <iostream>
#include "Personne.h"

using namespace std;


I c

int main()
ELH
{ U
Personne personne;
L MO
personne.setNom("wick");
f E
hre
personne.setPrenom("john");
c
c A
personne.setGenre(’M’);

personne.setNum(100);
personne.afficherDetails();
return 0;
}

En exécutant, le résultat est :


100 john wick M

Avril 2018 22 / 124


Classe Setter

C++
Testons avec une valeur autre que M ou F
#include <iostream>
#include "Personne.h"

using namespace std;


I c

int main()
ELH
{ U
Personne personne;
L MO
f
personne.setNom("wick");
E
hre
personne.setPrenom("john");
c
c A
personne.setGenre(’X’);

personne.setNum(100);
personne.afficherDetails();
return 0;
}

Avril 2018 23 / 124


Classe Setter

C++
Testons avec une valeur autre que M ou F
#include <iostream>
#include "Personne.h"

using namespace std;


I c

int main()
ELH
{ U
Personne personne;
L MO
personne.setNom("wick");
f E
hre
personne.setPrenom("john");
c
c A
personne.setGenre(’X’);

personne.setNum(100);
personne.afficherDetails();
return 0;
}

En exécutant, le résultat est :


100 john wick M

Avril 2018 23 / 124


Classe Getter

C++

Hypothèse

c

Si on voulait afficher les attributs (privés) de la classe Personne, un
I
par un, dans la fonction principale.
ELH
U
L MO
f E
c hre
c A

Avril 2018 24 / 124


Classe Getter

C++

Hypothèse

c

Si on voulait afficher les attributs (privés) de la classe Personne, un
I
par un, dans la fonction principale.
ELH
U
L MO
f E
Démarche A c hre
c
Définir des méthodes qui retournent les valeurs des attributs (les
getter)

Avril 2018 24 / 124


Classe Getter

C++
Les getters ajoutés dans Personne.h

class Personne
{
public :
void setNum(int const& num);
I c

void setNom(string const& nom);
void setPrenom(string const& prenom);
ELH
void setGenre(char const& genre);
U
int getNum() const;
L MO
string getNom() const;
f E
hre
string getPrenom() const;

c
char getGenre() const;

c A
void afficherDetails() const;

private:

int num;
string nom;
string prenom;
char genre;
};

Avril 2018 25 / 124


Classe Getter

C++
L’implémentation dans Personne.cpp

int Personne::getNum() const


{
return num;
}
I c

string Personne::getNom() const
ELH
{
U
return nom;
L MO
}
f E
c hre
string Personne::getPrenom() const

c A
{

}

return prenom;

char Personne::getGenre() const


{
return genre;
}

Avril 2018 26 / 124


Classe Getter

Mettons à jour la fonction principale


#include <iostream>
#include "Personne.h"
using namespace std;

int main()
{
I c

Personne personne;
personne.setNom("wick");
ELH
U
MO
personne.setPrenom("john");
personne.setGenre(’X’);
personne.setNum(100);
f E L
hre
cout << personne.getNum() << " " ;
c
c A
cout << personne.getNom() << " " ;

cout << personne.getPrenom() << " " ;
cout << personne.getGenre() << endl;
return 0;
}

Avril 2018 27 / 124


Classe Getter

Mettons à jour la fonction principale


#include <iostream>
#include "Personne.h"
using namespace std;

int main()
{
I c

Personne personne;
personne.setNom("wick");
ELH
U
MO
personne.setPrenom("john");
personne.setGenre(’X’);
personne.setNum(100);
f E L
hre
cout << personne.getNum() << " " ;
c
c A
cout << personne.getNom() << " " ;

cout << personne.getPrenom() << " " ;
cout << personne.getGenre() << endl;
return 0;
}

En exécutant, le résultat est :


100 wick john M
Avril 2018 27 / 124
Classe Constructeur

C++
Le constructeur
Une méthode particulière portant le nom de la classe et ne
retournant aucune valeur
I c
H
Toute classe en C++ a un constructeur par défaut sans paramètre
L
Ce constructeur sans paramètre n’aO UEcode
aucun
L M
r e f E
On peut le définir explicitement si un traitement est nécessaire (ou
c h
si on veut vérifier
A l’appel)
c
d’un objet de la classe (par exemple Personne
La déclaration
personne) fait appel à ce constructeur sans paramètre
Toutefois, et pour simplifier la création d’objets, on peut définir un
nouveau constructeur qui prend en paramètre plusieurs attributs

Avril 2018 28 / 124


Classe Constructeur

Commençons par définir le prototype de ce nouveau constructeur dans Personne.h

class Personne
{
public :
// constructeurs
Personne(int num, string nom, string prenom, char genre);
// setters et getters
void setNum(int num);
I c

void setNom(string nom);
void setPrenom(string prenom);
ELH
void setGenre(char genre);
U
int getNum() const;
L MO
string getNom() const;
f E
hre
string getPrenom() const;

c
char getGenre() const;

c A
// autres méthodes

void afficherDetails() const;

private:
int num;
string nom;
string prenom;
char genre;
};

Avril 2018 29 / 124


Classe Constructeur

C++

Implémentons le constructeur dans Personne.cpp : pour


préserver la cohérence, il faut que le constructeur contrôle la
valeur de l’attribut genre
Personne::Personne(int num, string nom, string
I c

prenom, char genre)
ELH
U
MO
{
this->num = num;
f E L
hre
this->nom = nom;
c
c A
this->prenom = prenom;

if (genre == ’F’ || genre == ’M’)
this->genre = genre;
else
this->genre = ’M’;
}

Avril 2018 30 / 124


Classe Constructeur

C++

On peut aussi appelé le setter dans le constructeur

I
Personne::Personne(int num, string nom, stringc

prenom, char genre)
ELH
U
MO
{
this->num = num;
f E L
hre
this->nom = nom;
c
c A
this->prenom = prenom;

}

this->setGenre(genre);

Avril 2018 31 / 124


Classe Constructeur

C++

C++ nous offre la possibilité d’initialiser les attributs de la


manière suivante
I c

Personne::Personne(int num, string nom, string
ELH
U
prenom, char genre) : num(num), nom(nom), prenom(
prenom)
L MO
{
f E
c hre
this->setGenre(genre);
}
c A

Avril 2018 32 / 124


Classe Constructeur

C++

C++ nous offre la possibilité d’initialiser les attributs de la


manière suivante
I c

Personne::Personne(int num, string nom, string
ELH
U
prenom, char genre) : num(num), nom(nom), prenom(
prenom)
L MO
{
f E
c hre
this->setGenre(genre);
}
c A

On peut initialiser nos attributs avec des constantes

Avril 2018 32 / 124


Classe Constructeur

Mettons à jour la fonction principale pour tester les deux constructeurs


#include <iostream>
#include "Personne.h"
using namespace std;

int main()
{
Personne personne;
personne.setNom("wick");
I c

personne.setPrenom("john");
ELH
personne.setGenre(’X’);
U
personne.setNum(100);
L
cout << personne.getNum() << " " ; MO
f E
hre
cout << personne.getNom() << " " ;
cout << personne.getPrenom() << endl;
c
c A
Personne personne2(101, "dalton", "jack", ’M’);

personne2.afficherDetails();
return 0;
}

Avril 2018 33 / 124


Classe Constructeur

Mettons à jour la fonction principale pour tester les deux constructeurs


#include <iostream>
#include "Personne.h"
using namespace std;

int main()
{
Personne personne;
personne.setNom("wick");
I c

personne.setPrenom("john");
ELH
personne.setGenre(’X’);
U
personne.setNum(100);
L
cout << personne.getNum() << " " ; MO
f E
hre
cout << personne.getNom() << " " ;
cout << personne.getPrenom() << endl;
c
c A
Personne personne2(101, "dalton", "jack", ’M’);

personne2.afficherDetails();
return 0;
}

Remarque

L’exécution du programme ⇒ une erreur.

Avril 2018 33 / 124


Classe Constructeur

C++

Explication
I c

ELH
Le constructeur par défaut a été écrasé (il n’existe plus)
U
L MO
f E
c hre
c A

Avril 2018 34 / 124


Classe Constructeur

C++

Explication
I c

ELH
Le constructeur par défaut a été écrasé (il n’existe plus)
U
L MO
f E
Solution
A c hre
c
Recréer un
constructeur sans paramètre

Avril 2018 34 / 124


Classe Constructeur

C++
Ajoutons le prototype du constructeur sans paramètre dans Personne.h
class Personne
{
public :
// constructeurs
I c

Personne();
ELH
Personne(int num, string nom, string prenom, char genre);
U
MO
// + les autres méthodes

private:
f E L
int num;
c hre
c A
string nom;

string prenom;
char genre;

Avril 2018 35 / 124


Classe Constructeur

C++
Ajoutons le prototype du constructeur sans paramètre dans Personne.h
class Personne
{
public :
// constructeurs
I c

Personne();
ELH
Personne(int num, string nom, string prenom, char genre);
U
MO
// + les autres méthodes

private:
f E L
int num;
c hre
c A
string nom;

string prenom;
char genre;

Implémentons ce nouveau constructeur dans Personne.cpp


Personne::Personne() { }

Avril 2018 35 / 124


Classe Constructeur

Testons maintenantle contenu précédent de la fonction principale

#include <iostream>
#include "Personne.h"
using namespace std;

int main()
{
Personne personne;
I c

personne.setNom("wick");
personne.setPrenom("john");
ELH
U
MO
personne.setGenre(’X’);
personne.setNum(100);

E L
cout << personne.getNum() << " " ;
f
hre
cout << personne.getNom() << " " ;

c
cout << personne.getPrenom() << endl;

c A
Personne personne2(101, "dalton", "jack", ’M’);

personne2.afficherDetails();
return 0;
}

Avril 2018 36 / 124


Classe Constructeur

Testons maintenantle contenu précédent de la fonction principale

#include <iostream>
#include "Personne.h"
using namespace std;

int main()
{
Personne personne;
I c

personne.setNom("wick");
personne.setPrenom("john");
ELH
U
MO
personne.setGenre(’X’);
personne.setNum(100);
cout << personne.getNum() << " " ;
f E L
hre
cout << personne.getNom() << " " ;

c
cout << personne.getPrenom() << endl;

c A
Personne personne2(101, "dalton", "jack", ’M’);

personne2.afficherDetails();
return 0;
}

En exécutant, le résultat est :


100 wick john
101 jack dalton M

Avril 2018 36 / 124


Classe Constructeur

On peut aussi déclarer un pointeur et utiliser le constructeur à plusieurs paramètres

#include <iostream>
#include "Personne.h"
using namespace std;

int main()
{
Personne personne;
I c

personne.setNom("wick");
personne.setPrenom("john");
ELH
U
MO
personne.setGenre(’X’);
personne.setNum(100);

E L
cout << personne.getNum() << " " ;
f
hre
cout << personne.getNom() << " " ;

c
cout << personne.getPrenom() << endl;

c A
Personne *personne2 = new Personne (101, "dalton", "jack", ’M’);

personne2->afficherDetails();
return 0;
}

Avril 2018 37 / 124


Classe Constructeur

On peut aussi déclarer un pointeur et utiliser le constructeur à plusieurs paramètres

#include <iostream>
#include "Personne.h"
using namespace std;

int main()
{
Personne personne;
I c

personne.setNom("wick");
personne.setPrenom("john");
ELH
U
MO
personne.setGenre(’X’);
personne.setNum(100);

E
cout << personne.getNum() << " " ;
f L
hre
cout << personne.getNom() << " " ;

c
cout << personne.getPrenom() << endl;

c A
Personne *personne2 = new Personne (101, "dalton", "jack", ’M’);

personne2->afficherDetails();
return 0;
}

En exécutant, le résultat est évidemment le même :


100 wick john
101 jack dalton M

Avril 2018 37 / 124


Classe Constructeur de copie

C++
Considérons l’objet de la classe Personne suivant
Personne personne2(101, "dalton", "jack", ’M’);

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 38 / 124


Classe Constructeur de copie

C++
Considérons l’objet de la classe Personne suivant
Personne personne2(101, "dalton", "jack", ’M’);

I c

LH
Et si on veut copier cet objet dans un nouveau, il va falloir faire
E
U
MO
Personne personne3(personne2);
L
h r e fE
A c
c

Avril 2018 38 / 124


Classe Constructeur de copie

C++
Considérons l’objet de la classe Personne suivant
Personne personne2(101, "dalton", "jack", ’M’);

I c

LH
Et si on veut copier cet objet dans un nouveau, il va falloir faire
E
U
Personne personne3(personne2);
L MO
h r e fE
A c
c
le compilateur a un autre avis
Malheureusement,
ça marche pour les autres variables
mais pour les objets qu’on crée de nos classes personnalisées, il
faut un constructeur de copie

Avril 2018 38 / 124


Classe Constructeur de copie

C++
Commençons par définir le constructeur dans Personne.h

Personne(Personne const& objetACopier);

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 39 / 124


Classe Constructeur de copie

C++
Commençons par définir le constructeur dans Personne.h

Personne(Personne const& objetACopier);

I c

Explication
ELH
U
MO
objetACopier : objet à copier

f E L
const& : le but n’est pas de modifier l’objet à copier

c hre
c A

Avril 2018 39 / 124


Classe Constructeur de copie

C++
Commençons par définir le constructeur dans Personne.h

Personne(Personne const& objetACopier);

I c

Explication
ELH
U
MO
objetACopier : objet à copier

f E L
const& : le but n’est pas de modifier l’objet à copier

c hre
c A

Ensuite, implémentons ce constructeur dans Personne.cpp

Personne::Personne(Personne const& objetACopier): num(objetACopier.num)


, nom(objetACopier.nom), prenom(objetACopier.prenom)
{
this->setGenre(objetACopier.genre);
}

Avril 2018 39 / 124


Classe Constructeur de copie

C++

c

Maintenant, on peut copier les objets comme des simples
I
variables
E L H
O U
Personne personne2(101, "dalton", "jack", ’M’);
L M
f E
Personne personne3(personne2);
redalton M
personne3.afficherDetails();
c h
c A
// affiche 101 jack

Avril 2018 40 / 124


Classe Constructeur de conversion

C++

Constructeur de conversion (C++ 11)


I c
E H
L d’affecter une
Un constructeur de conversion permet à l’utilisateur
valeur à un objet d’une classe commeO U
s’il s’agit d’une simple
L M
variable
e f E
Un constructeur c derconversion a comme rôle la construction d’un
h
cpartirAd’une affectation
objet à

Avril 2018 41 / 124


Classe Constructeur de conversion

C++
Commençons par définir le prototype de ce constructeur dans Personne.h

Personne (int num);

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 42 / 124


Classe Constructeur de conversion

C++
Commençons par définir le prototype de ce constructeur dans Personne.h

Personne (int num);

Implémentons ce constructeur dans Personne.cpp


I c

ELH
U
Personne::Personne(int num) : num(num), nom("doe"), prenom("john"),

{
genre(’M’)

L MO
f E
}
c hre
c A

Avril 2018 42 / 124


Classe Constructeur de conversion

C++
Commençons par définir le prototype de ce constructeur dans Personne.h

Personne (int num);

Implémentons ce constructeur dans Personne.cpp


I c

ELH
U
Personne::Personne(int num) : num(num), nom("doe"), prenom("john"),

{
genre(’M’)

L MO
f E
}
c hre
c A

Testons ce constructeur dans le main

Personne personne = 99;


cout << personne.getNum() << " " << personne.getNom() << " " <<
personne.getPrenom() << endl;
// affiche 99 doe john

Avril 2018 42 / 124


Classe Destructeur

C++

Le destructeur
I c
EL H
Une méthode portant le nom de la classe et précédée par ∼
réfO
Appelé lorsque l’objet n’est plusM
U
érencé ou si l’opérateur
delete est utilisé.
fE L
L’opérateur A h r e
c est utilisé pour les objets dynamiques créés
delete
c
érateur new
avec l’op

Avril 2018 43 / 124


Classe Destructeur

Définissons le prototype du destructeur dans Personne.h

class Personne
{
public :
// constructeurs
Personne();
Personne(int num, string nom, string prenom, char genre);
// desctructeur
I c

˜Personne();
// + les autres méthodes
ELH
U
private:
L MO
int num;
f E
hre
string nom;
string prenom;
c
c A
char genre;

Avril 2018 44 / 124


Classe Destructeur

Définissons le prototype du destructeur dans Personne.h

class Personne
{
public :
// constructeurs
Personne();
Personne(int num, string nom, string prenom, char genre);
// desctructeur
I c

˜Personne();
// + les autres méthodes
ELH
U
private:
L MO
int num;
f E
hre
string nom;
string prenom;
c
c A
char genre;

Implémentons le destructeur dans Personne.cpp

Personne::˜Personne()
{
cout << "objet personne num " << num << " detruit" << endl;
}

Avril 2018 44 / 124


Classe Destructeur

On peut aussi déclarer un pointeur et utiliser le constructeur à plusieurs paramètres


#include <iostream>
#include "Personne.h"
using namespace std;

int main()
{
Personne personne(100, "wick", "john", ’M’);
personne.afficherDetails();
I c

ELH
Personne *personne2 = new Personne (101, "dalton", "jack", ’M’);
personne2->afficherDetails();
U
}
return 0;
L MO
f E
c hre
c A

Avril 2018 45 / 124


Classe Destructeur

On peut aussi déclarer un pointeur et utiliser le constructeur à plusieurs paramètres


#include <iostream>
#include "Personne.h"
using namespace std;

int main()
{
Personne personne(100, "wick", "john", ’M’);
personne.afficherDetails();
I c

ELH
Personne *personne2 = new Personne (101, "dalton", "jack", ’M’);
personne2->afficherDetails();
U
}
return 0;
L MO
f E
hre
En exécutant, (Suprise) le résultat est
c
c A
100 john wick M

101 jack dalton M
objet personne num 100 detruit

Avril 2018 45 / 124


Classe Destructeur

On peut aussi déclarer un pointeur et utiliser le constructeur à plusieurs paramètres


#include <iostream>
#include "Personne.h"
using namespace std;

int main()
{
Personne personne(100, "wick", "john", ’M’);
personne.afficherDetails();
I c

ELH
Personne *personne2 = new Personne (101, "dalton", "jack", ’M’);
personne2->afficherDetails();
U
}
return 0;
L MO
f E
hre
En exécutant, (Suprise) le résultat est
c
100 john wick M
101 jack dalton Mc A

objet personne num 100 detruit

Pourquoi le deuxième objet n’a pas été détruit ?

car il s’agit d’un pointeur

il faut utiliser l’opérateur delete()

Avril 2018 45 / 124


Classe Destructeur

C++
On peut aussi déclarer un pointeur et utiliser le constructeur à plusieurs paramètres
#include <iostream>
#include "Personne.h"
using namespace std;

int main()
{
I c

Personne personne(100, "wick", "john", ’M’);
ELH
personne.afficherDetails();
U
personne2->afficherDetails();
L MO
Personne *personne2 = new Personne (101, "dalton", "jack", ’M’);

f E
hre
delete(personne2);
return 0;
c
c A
}

Avril 2018 46 / 124


Classe Destructeur

C++
On peut aussi déclarer un pointeur et utiliser le constructeur à plusieurs paramètres
#include <iostream>
#include "Personne.h"
using namespace std;

int main()
{
I c

Personne personne(100, "wick", "john", ’M’);
ELH
personne.afficherDetails();
U
personne2->afficherDetails();
L MO
Personne *personne2 = new Personne (101, "dalton", "jack", ’M’);

f E
hre
delete(personne2);
return 0;
c
c A
}

En exécutant, le résultat est
100 john wick M
101 jack dalton M
objet personne num 101 detruit
objet personne num 100 detruit
Avril 2018 46 / 124
Classe Attributs et méthodes statiques

C++
Récapitulatif

Les instances d’une même classe ont toutes les mêmes attributs mais
pas les mêmes valeurs
I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 47 / 124


Classe Attributs et méthodes statiques

C++
Récapitulatif

Les instances d’une même classe ont toutes les mêmes attributs mais
pas les mêmes valeurs
I c

ELH
U
Hypothèse
L MO
f E
hre
Et si nous voulions qu’un attribut ait une valeur partagée par toutes les
c
instances (le nombre d’objets instanciés de la classe Personne)
c A

Avril 2018 47 / 124


Classe Attributs et méthodes statiques

C++
Récapitulatif

Les instances d’une même classe ont toutes les mêmes attributs mais
pas les mêmes valeurs
I c

ELH
U
Hypothèse
L MO
f E
hre
Et si nous voulions qu’un attribut ait une valeur partagée par toutes les
c
instances (le nombre d’objets instanciés de la classe Personne)
c A

Définition
Un attribut dont la valeur est partagée par toutes les instances de la
classe est appelée : attribut statique ou attribut de classe

Avril 2018 47 / 124


Classe Attributs et méthodes statiques

C++

Exemple
I c

E H
L des objets créés
Si on veut créer un attribut contenant le nombre
U
à partir de la classe Personne
L MO
r e
Notre attribut doit être
h f E sinon chaque objet pourrait avoir
static,
A
sa propre valeur c pour cet attribut
c

Avril 2018 48 / 124


Classe Attributs et méthodes statiques

Ajoutons un attribut static appelé nbrPersonnes dans Personne.h


class Personne
{
public:
// les méthodes
private:
// les autres attributs
static int nbrPersonnes;
I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 49 / 124


Classe Attributs et méthodes statiques

Ajoutons un attribut static appelé nbrPersonnes dans Personne.h


class Personne
{
public:
// les méthodes
private:
// les autres attributs
static int nbrPersonnes;
I c

ELH
U
Dans Personne.cpp, nous initialisons la valeur de cet attribut static et nous
l’incrémentons dans les quatre constructeurs

L MO
f
int Personne::nbrPersonnes = 0;
E
Personne::Personne()
c hre
{

}
c A

nbrPersonnes++;

Personne::Personne(int num, string nom, string prenom, char genre) :


num(num), nom(nom), prenom(prenom)
{
this->setGenre(genre);
nbrPersonnes++;
}

Avril 2018 49 / 124


Classe Attributs et méthodes statiques

C++

Définissons un getter pour l’attribut static nbrPersonnes dans


Personne.h
static int getNbrPersonnes(); I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 50 / 124


Classe Attributs et méthodes statiques

C++

Définissons un getter pour l’attribut static nbrPersonnes dans


Personne.h
static int getNbrPersonnes(); I c

ELH
U
L MO
f E
Implémentons ce getter dans Personne.cpp
c hre
c A
int Personne::getNbrPersonnes()
{
return nbrPersonnes;
}

Avril 2018 50 / 124


Classe Attributs et méthodes statiques

C++
Testons cela dans la classe Main
#include <iostream>
#include "Personne.h"
using namespace std;

int main()
I c

{
Personne personne(100, "wick", "john", ’M’);
ELH
U
cout << Personne::getNbrPersonnes() << endl;

MO
Personne *personne2 = new Personne (101, "dalton", "jack", ’M’);
L
E
cout << Personne::getNbrPersonnes() << endl;
f
hre
delete(personne2);
return 0;
c
c A
}

Avril 2018 51 / 124


Classe Attributs et méthodes statiques

C++
Testons cela dans la classe Main
#include <iostream>
#include "Personne.h"
using namespace std;

int main()
I c

{
Personne personne(100, "wick", "john", ’M’);
ELH
U
cout << Personne::getNbrPersonnes() << endl;

MO
Personne *personne2 = new Personne (101, "dalton", "jack", ’M’);
L
E
cout << Personne::getNbrPersonnes() << endl;
f
hre
delete(personne2);
return 0;
c
c A
}

Le résultat est
1
2
objet personne num 101 detruit
objet personne num 100 detruit
Avril 2018 51 / 124
Classe Fonction amie

C++

Fonction amie (friend function)

I c
Fonction dont le prototype est déclaré dans une classe (comme
EL
toute méthode) mais avec le mot-clé friend H
U
MneOdoit pas être préfixée par
L’implémentation de cette fonction
L
e
NomClasse::nomMethode()
h r fE
A
Cette fonction cprend généralement comme paramètre un objet de
c
et elle a donc accès à tous ses attributs privés et
cette classe
protégés

Avril 2018 52 / 124


Classe Fonction amie

C++
Définissons une fonction amie dans Personne.h (& pour pouvoir modifier l’objet)

friend void devenirNiHommeNiFemme(Personne & p);

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 53 / 124


Classe Fonction amie

C++
Définissons une fonction amie dans Personne.h (& pour pouvoir modifier l’objet)

friend void devenirNiHommeNiFemme(Personne & p);

I c

H
Implémentons cette méthode dans main.cpp (par exemple)

EL
U
MO
void devenirNiHommeNiFemme(Personne & p)
{
p.genre = ’D’;
f E L
hre
}

c
c A

Avril 2018 53 / 124


Classe Fonction amie

C++
Définissons une fonction amie dans Personne.h (& pour pouvoir modifier l’objet)

friend void devenirNiHommeNiFemme(Personne & p);

I c

H
Implémentons cette méthode dans main.cpp (par exemple)

EL
U
MO
void devenirNiHommeNiFemme(Personne & p)
{
p.genre = ’D’;
f E L
hre
}

c
c A

Testons cette fonction amie dans le main

Personne personne(100, "wick", "john", ’M’)


devenirNiHommeNiFemme(personne);
personne.afficherDetails();
// affiche john wick D

Avril 2018 53 / 124


Classe Fonction inline

C++

Méthode inline

I c
Une méthode implémentée dans le fichier .h est implicitement
inline EL H
U
L MO
Une méthode préfixée par inline est explicitement inline
E
f explicitement inline doit être défini
rmeéthode
h
Le prototype d’une
c
c A .h. Son implémentation doit donc être dans le .h
dans un fichier

Les getter et setter est un bon exemple de méthode inline

Avril 2018 54 / 124


Classe Fonction inline

C++
Pour tester, modifions quelques déclarations dans Personne.h
inline void setNum(int const& num);
void setNom(string const& nom) { this->nom = nom;};

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 55 / 124


Classe Fonction inline

C++
Pour tester, modifions quelques déclarations dans Personne.h
inline void setNum(int const& num);
void setNom(string const& nom) { this->nom = nom;};

I c

la méthode setNum() est explicitement déclarée inline, il faut donc l’implémenter dans
Personne.h après la classe
ELH
U
MO
void Personne::setNum(int const& num)
{
this->num = num;
f E L
hre
}
c
c A

Avril 2018 55 / 124


Classe Fonction inline

C++
Pour tester, modifions quelques déclarations dans Personne.h
inline void setNum(int const& num);
void setNom(string const& nom) { this->nom = nom;};

I c

la méthode setNum() est explicitement déclarée inline, il faut donc l’implémenter dans
Personne.h après la classe
ELH
U
MO
void Personne::setNum(int const& num)
{
this->num = num;
f E L
hre
}
c
c A

Testons les nouveaux setters dans le main
Personne personne(100, "wick", "john", ’M’);
personne.setNum(99);
personne.setNom("abruzzi");
personne.afficherDetails();
// affiche 99 john abruzzi M
// objet personne num 99 detruit
Avril 2018 55 / 124
Classe Opérateur de conversion

C++

Opérateur de conversion (C++ 11)


I c
H
EdeLconversion : un
U
Une classe peut avoir plusieurs opérateurs
opérateur au plus par type
L MO
r e f Epermet de convertir un objet de cette
L’opérateur de conversion
h
classe type A c ou primitif)
(objet
c

Avril 2018 56 / 124


Classe Opérateur de conversion

C++
Dans Personne.h, commençons par définir un opérateur qui transforme un objet de type
Personne en int

operator int();

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 57 / 124


Classe Opérateur de conversion

C++
Dans Personne.h, commençons par définir un opérateur qui transforme un objet de type
Personne en int

operator int();

I c

Implémentons cet opérateur dans Personne.cpp
ELH
U
MO
Personne::operator int()
{
return num;
f E L
hre
}

c
c A

Avril 2018 57 / 124


Classe Opérateur de conversion

C++
Dans Personne.h, commençons par définir un opérateur qui transforme un objet de type
Personne en int

operator int();

I c

Implémentons cet opérateur dans Personne.cpp
ELH
U
MO
Personne::operator int()
{
return num;
f E L
hre
}

c
c A

Testons cet opérateur dans le main

Personne personne(100, "wick", "john", ’M’);


int x = personne;
cout << x << endl;
// affiche 100
// objet personne num 100 detruit

Avril 2018 57 / 124


Association simple entre classes Association simple sans pointeur

C++

Exercice
Définir une classe Adresse avec trois attributs privés (rue,
codePostal et ville) de type chaı̂ne de caractère
I c

ELH
Définir un constructeur avec trois paramètres, les getters et les
U
MO
setters

f E L
Dans la classe Personne, ajouter un attribut adresse de type
c hre
Adresse et définir un nouveau constructeur à quatre paramètres
c A

et le getter et le setter de ce nouvel attribut
Dans la fonction principale main, créer un objet de type Adresse
et l’affecter à un de type Personne (qu’il faut créer aussi)
Afficher tous les attributs de cet objet de la classe Personne

Avril 2018 58 / 124


Association simple entre classes Association simple sans pointeur

Le fichier Adresse.h

#ifndef ADRESSE_H_INCLUDED
#define ADRESSE_H_INCLUDED
#include <string>
using namespace std;

class Adresse
{
I c

public :
Adresse();
ELH
U
Adresse(string rue, string codePostal, string ville);
void setRue(string const& rue);
L MO
E
void setVille(string const& ville);
f
hre
void setCodePostal(string const& codePostal);

c
string getRue() const;

c A
string getVille() const;

string getCodePostal() const;

private:
string rue;
string codePostal;
string ville;
};
#endif // ADRESSE_H_INCLUDED

Avril 2018 59 / 124


Association simple entre classes Association simple sans pointeur

C++
Le fichier Adresse.cpp (partie 1)
#include "Personne.h"

using namespace std;

Adresse::Adresse()
I c

{
}
ELH
U
MO
Adresse::Adresse(string rue, string codePostal, string ville): rue(rue)
L
E
, ville(ville), codePostal(codePostal)
f
hre
{
}
c
c A

void Adresse::setRue(string rue)
{
this->rue = rue;
}

void Adresse::setVille(string ville)


{
this->ville = ville;
}
Avril 2018 60 / 124
Association simple entre classes Association simple sans pointeur

C++
Le fichier Adresse.cpp (partie 2)

void Adresse::setCodePostal(string codePostal)


{
this->codePostal = codePostal;
}
I c

string Adresse::getRue() const
ELH
{
U
return rue;
L MO
}
f E
c hre
string Adresse::getVille() const

c A
{

}

return ville;

string Adresse::getCodePostal() const


{
return codePostal;
}

Avril 2018 61 / 124


Association simple entre classes Association simple sans pointeur

C++
Importons la classe Adresse dans Personne.h
#include "Adresse.h"

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 62 / 124


Association simple entre classes Association simple sans pointeur

C++
Importons la classe Adresse dans Personne.h
#include "Adresse.h"

Déclarons un attribut de type Adresse dans Personne.h


I c

Adresse adresse;
ELH
U
L MO
f E
c hre
c A

Avril 2018 62 / 124


Association simple entre classes Association simple sans pointeur

C++
Importons la classe Adresse dans Personne.h
#include "Adresse.h"

Déclarons un attribut de type Adresse dans Personne.h


I c

Adresse adresse;
EL H
U
L MetO
Définissons un nouveau constructeur les getter/setter

r e
// le nouveau constructeur
h fE
Personne(int num,
A c string nom, string prenom, char genre,
Adressecadresse);

// le setter
void setAdresse(Adresse adresse);

// le getter
Adresse getAdresse() const;
Avril 2018 62 / 124
Association simple entre classes Association simple sans pointeur

Importons la classe Adresse dans Personne.cpp


#include "Adresse.h"

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 63 / 124


Association simple entre classes Association simple sans pointeur

Importons la classe Adresse dans Personne.cpp


#include "Adresse.h"

Implémentons le nouveau constructeur dans Personne.cpp


Personne::Personne(int num, string nom, string prenom, char genre,
Adresse adresse): num(num), nom(nom), prenom(prenom), adresse(
adresse)
I c

{
this->setGenre(genre);
ELH
U
MO
nbrPersonnes++;
}

f E L
c hre
c A

Avril 2018 63 / 124


Association simple entre classes Association simple sans pointeur

Importons la classe Adresse dans Personne.cpp


#include "Adresse.h"

Implémentons le nouveau constructeur dans Personne.cpp


Personne::Personne(int num, string nom, string prenom, char genre,
Adresse adresse): num(num), nom(nom), prenom(prenom), adresse(
adresse)
I c

{
this->setGenre(genre);
ELH
U
MO
nbrPersonnes++;
}

f E L
hre
Implémentons les getter/setter dans Personne.cpp
c
c A

void Personne::setAdresse(Adresse adresse)
{
this->adresse = adresse;
}

Adresse Personne::getAdresse() const


{
return adresse;
}

Avril 2018 63 / 124


Association simple entre classes Association simple sans pointeur

C++
Testons cela dans la fonction principale main
#include <iostream>
#include "Personne.h"

using namespace std;


I c

int main()
ELH
{ U
Adresse adresse("paradis", "13015", "Marseille");
L MO
f E
Personne personne3(102, "jordan", "mike", ’M’, adresse);

hre
cout << personne3.getNom() << " " ;
c
c A
cout << personne3.getPrenom() << " " ;

cout << personne3.getAdresse().getCodePostal() << endl;
return 0;
}

Avril 2018 64 / 124


Association simple entre classes Association simple sans pointeur

C++
Testons cela dans la fonction principale main
#include <iostream>
#include "Personne.h"

using namespace std;


I c

int main()
ELH
{ U
Adresse adresse("paradis", "13015", "Marseille");
L MO
f E
Personne personne3(102, "jordan", "mike", ’M’, adresse);

hre
cout << personne3.getNom() << " " ;
c
c A
cout << personne3.getPrenom() << " " ;

cout << personne3.getAdresse().getCodePostal() << endl;
return 0;
}

Le résultat est
jordan mike 13015
Avril 2018 64 / 124
Association simple entre classes Association simple sans pointeur

C++
Essayons de modifier le code postal de cette personne
#include <iostream>
#include "Personne.h"

using namespace std;

int main()
I c

{
ELH
Adresse adresse("paradis", "13015", "Marseille");
U
L MO
Personne personne3(102, "jordan", "mike", ’M’, adresse);
cout << personne3.getAdresse().getCodePostal() << endl;
f E
hre
// affiche 13015

c
personne3.getAdresse().setCodePostal("69000");

c A
cout << personne3.getAdresse().getCodePostal() << endl;

// affiche 13015
return 0;
}

Avril 2018 65 / 124


Association simple entre classes Association simple sans pointeur

C++
Essayons de modifier le code postal de cette personne
#include <iostream>
#include "Personne.h"

using namespace std;

int main()
I c

{
ELH
Adresse adresse("paradis", "13015", "Marseille");
U
L MO
Personne personne3(102, "jordan", "mike", ’M’, adresse);
cout << personne3.getAdresse().getCodePostal() << endl;
f E
hre
// affiche 13015

c
personne3.getAdresse().setCodePostal("69000");

c A
cout << personne3.getAdresse().getCodePostal() << endl;

// affiche 13015
return 0;
}

Question
Pourquoi le code postal n’a pas été changé ?

Avril 2018 65 / 124


Association simple entre classes Association simple sans pointeur

C++
Réponse
Car le getter d’adresse dans Personne retourne une valeur (pas
une référence)

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 66 / 124


Association simple entre classes Association simple sans pointeur

C++
Réponse
Car le getter d’adresse dans Personne retourne une valeur (pas
une référence)

I c

EL H
U
Modifions getAdresses() dans Personne.h
O
Adresse & getAdresse(); L M

h r e fE
A c
c

Avril 2018 66 / 124


Association simple entre classes Association simple sans pointeur

C++
Réponse
Car le getter d’adresse dans Personne retourne une valeur (pas
une référence)

I c

EL H
U
Modifions getAdresses() dans Personne.h
O
Adresse & getAdresse(); L M

h r e fE
A c
Modifions c
getAdresses() dans Personne.cpp
Adresse & Personne::getAdresse()
{
return adresse;
}

Avril 2018 66 / 124


Association simple entre classes Association simple sans pointeur

C++
En testant maintenant, le code postal a bien été modifié
#include <iostream>
#include "Personne.h"

using namespace std;


I c

int main()
ELH
U
MO
{
Adresse adresse("paradis", "13015", "Marseille");

f E L
hre
Personne personne3(102, "jordan", "mike", ’M’, adresse);
c
c A
cout << personne3.getAdresse().getCodePostal() << endl;

// affiche 13015

personne3.getAdresse().setCodePostal("69000");
cout << personne3.getAdresse().getCodePostal() << endl;
// affiche 69000
return 0;
}

Avril 2018 67 / 124


Association simple entre classes Association simple avec pointeur

C++

Différence avec la solution précédente

I c
Dans la classe Personne, ajouter un pointeur vers la classe
Adresse *adresse EL H
U
L MetO
Modifier le constructeur, le getter le setter de ce nouvel attribut
Dans la fonction h
E
ref main, créer un pointeur sur Adresse
principale
c
c Aun de type Personne
et l’affecter à

Afficher tous les attributs de cet objet de la classe Personne

Avril 2018 68 / 124


Association simple entre classes Association simple avec pointeur

C++
Déclarons un pointeur sur Adresse dans Personne.h
Adresse *adresse;

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 69 / 124


Association simple entre classes Association simple avec pointeur

C++
Déclarons un pointeur sur Adresse dans Personne.h
Adresse *adresse;

I c

H
Adaptons les nouvelles signatures des constructeur, getter et
EL
setter U
L
// le nouveau constructeur MO
r e f E nom, string prenom, char
Personne(int num, string
h
A c *adresse);
genre, Adresse
c
// le setter
void setAdresse(Adresse *adresse);

// le getter
Adresse * getAdresse() const;
Avril 2018 69 / 124
Association simple entre classes Association simple avec pointeur

C++
Dans Personne.cpp, rien ne change à part la signature pour le constructeur
Personne::Personne(int num, string nom, string prenom, char genre,
Adresse *adresse): num(num), nom(nom), prenom(prenom), adresse(
adresse)
{
this->setGenre(genre);
I c

}
nbrPersonnes++;

ELH
U
L MO
f E
c hre
c A

Avril 2018 70 / 124


Association simple entre classes Association simple avec pointeur

C++
Dans Personne.cpp, rien ne change à part la signature pour le constructeur
Personne::Personne(int num, string nom, string prenom, char genre,
Adresse *adresse): num(num), nom(nom), prenom(prenom), adresse(
adresse)
{
this->setGenre(genre);
I c

}
nbrPersonnes++;

ELH
U
L MO
f E
hre
De même pour les getter/setter
c
c A
void Personne::setAdresse(Adresse *adresse)
{

this->adresse = adresse;
}

Adresse * Personne::getAdresse() const


{
return adresse;
}

Avril 2018 70 / 124


Association simple entre classes Association simple avec pointeur

C++
Modifions l’instanciation d’Adresse et la récupération du codePostal

#include <iostream>
#include "Personne.h"

using namespace std;

I c

int main()
{
ELH
U
MO
Adresse *adresse = new Adresse("paradis", "13015", "Marseille");

f E L
Personne personne3(102, "jordan", "mike", ’M’, adresse);
cout << personne3.getNom() << " " ;

hre
cout << personne3.getPrenom() << " " ;
c
cout << personne3.getAdresse()->getCodePostal() << endl;

}
return 0;
c A

Avril 2018 71 / 124


Association simple entre classes Association simple avec pointeur

C++
Modifions l’instanciation d’Adresse et la récupération du codePostal

#include <iostream>
#include "Personne.h"

using namespace std;

I c

int main()
{
ELH
U
MO
Adresse *adresse = new Adresse("paradis", "13015", "Marseille");

f E L
Personne personne3(102, "jordan", "mike", ’M’, adresse);
cout << personne3.getNom() << " " ;

hre
cout << personne3.getPrenom() << " " ;
c
cout << personne3.getAdresse()->getCodePostal() << endl;

}
return 0;
c A

Le résultat est

jordan mike 13015

Avril 2018 71 / 124


Association simple entre classes Association simple avec pointeur

Si on copie l’objet personne et on modifie l’adresse


Adresse *adresse = new Adresse("paradis", "13015", "Marseille");
Personne personne3(102, "jordan", "mike", ’M’, adresse);
cout << personne3.getNom() << " " ;
cout << personne3.getPrenom() << " " ;
cout << personne3.getAdresse()->getCodePostal() << endl;

Personne personne4(personne3);
personne3.getAdresse()->setCodePostal("13008");
I c

cout << personne4.getNom() << " " ;
ELH
cout << personne4.getPrenom() << " " ;
U
MO
cout << personne4.getAdresse()->getCodePostal() << endl;
L
f E
c hre
c A

Avril 2018 72 / 124


Association simple entre classes Association simple avec pointeur

Si on copie l’objet personne et on modifie l’adresse


Adresse *adresse = new Adresse("paradis", "13015", "Marseille");
Personne personne3(102, "jordan", "mike", ’M’, adresse);
cout << personne3.getNom() << " " ;
cout << personne3.getPrenom() << " " ;
cout << personne3.getAdresse()->getCodePostal() << endl;

Personne personne4(personne3);
personne3.getAdresse()->setCodePostal("13008");
I c

cout << personne4.getNom() << " " ;
ELH
cout << personne4.getPrenom() << " " ;
U
cout << personne4.getAdresse()->getCodePostal() << endl;
L MO
f E
Surprise, le résultat est
chre
c A

jordan mike 13015
jordan mike 13008

Avril 2018 72 / 124


Association simple entre classes Association simple avec pointeur

Si on copie l’objet personne et on modifie l’adresse


Adresse *adresse = new Adresse("paradis", "13015", "Marseille");
Personne personne3(102, "jordan", "mike", ’M’, adresse);
cout << personne3.getNom() << " " ;
cout << personne3.getPrenom() << " " ;
cout << personne3.getAdresse()->getCodePostal() << endl;

Personne personne4(personne3);
personne3.getAdresse()->setCodePostal("13008");
I c

cout << personne4.getNom() << " " ;
ELH
cout << personne4.getPrenom() << " " ;
U
cout << personne4.getAdresse()->getCodePostal() << endl;
L MO
f E
Surprise, le résultat est
chre
c A

jordan mike 13015
jordan mike 13008

Explication

personne3 et personne4 pointent sur le même objet adresse

Avril 2018 72 / 124


Association simple entre classes Association simple avec pointeur

C++
Comment corriger ça ?

Créer un constructeur de copie pour Adresse

Utiliser ce dernier dans le constructeur de copie de Personne

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 73 / 124


Association simple entre classes Association simple avec pointeur

C++
Comment corriger ça ?

Créer un constructeur de copie pour Adresse

Utiliser ce dernier dans le constructeur de copie de Personne

I c

EL H
U
O Adresse.h
Mdans
Définissons le prototype de ce constructeur
L
e fE
Adresse(Adresse const& objetACopier);
h r
A c
c

Avril 2018 73 / 124


Association simple entre classes Association simple avec pointeur

C++
Comment corriger ça ?

Créer un constructeur de copie pour Adresse

Utiliser ce dernier dans le constructeur de copie de Personne

I c

EL H
U
O Adresse.h
Mdans
Définissons le prototype de ce constructeur
L
e fE
Adresse(Adresse const& objetACopier);
h r
A c
c
Implémentons ce constructeur dans Adresse.cpp
Adresse::Adresse(Adresse const& objetACopier): rue(objetACopier
.rue), ville(objetACopier.ville), codePostal(objetACopier.
codePostal)
{
}

Avril 2018 73 / 124


Association simple entre classes Association simple avec pointeur

C++
Utilisons ce constructeur dans le constructeur de copie défini dans Personne.cpp
Personne::Personne(Personne const& objetACopier): num(objetACopier.num)
, nom(objetACopier.nom), prenom(objetACopier.prenom)
{
this->setGenre(objetACopier.genre);
this->adresse = new Adresse(*(objetACopier.adresse));
I c

}

ELH
U
L MO
f E
c hre
c A

Avril 2018 74 / 124


Association simple entre classes Association simple avec pointeur

C++
Utilisons ce constructeur dans le constructeur de copie défini dans Personne.cpp
Personne::Personne(Personne const& objetACopier): num(objetACopier.num)
, nom(objetACopier.nom), prenom(objetACopier.prenom)
{
this->setGenre(objetACopier.genre);
this->adresse = new Adresse(*(objetACopier.adresse));
I c

}

ELH
U
L MO
Ne changeons rien dans le main
f E
hre
Adresse *adresse = new Adresse("paradis", "13015", "Marseille");
c
c A
Personne personne3(102, "jordan", "mike", ’M’, adresse);


cout << personne3.getNom() << " " ;
cout << personne3.getPrenom() << " " ;
cout << personne3.getAdresse()->getCodePostal() << endl;

Personne personne4(personne3);
personne3.getAdresse()->setCodePostal("13008");
cout << personne4.getNom() << " " ;
cout << personne4.getPrenom() << " " ;
cout << personne4.getAdresse()->getCodePostal() << endl;
Avril 2018 74 / 124
Association simple entre classes Association simple avec pointeur

C++

I c

En exécutant, le résultat est cette fois-ci correct
ELH
U
jordan mike 13015
L MO
jordan mike 13015
f E
c hre
c A

Avril 2018 75 / 124


Héritage

C++

L’héritage, quand ?
Lorsque deux ou plusieurs classes partagent plusieurs attributs
(et méthodes)
I c

EL H
Lorsqu’une Classe1 est une [sorte de] Classe2
U
L MO
h r e fE
A c
c

Avril 2018 76 / 124


Héritage

C++

L’héritage, quand ?
Lorsque deux ou plusieurs classes partagent plusieurs attributs
(et méthodes)
I c

EL H
Lorsqu’une Classe1 est une [sorte de] Classe2
U
L MO
h r e fE
Forme généraleAc
c
class ClasseFille : modeDeVisivility ClasseMère
{
// code
};

Avril 2018 76 / 124


Héritage Héritage simple

C++
Exemple

Un enseignant a un numéro, un nom, un prénom, un genre et un salaire

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 77 / 124


Héritage Héritage simple

C++
Exemple

Un enseignant a un numéro, un nom, un prénom, un genre et un salaire

c

Un étudiant a aussi un numéro, un nom, un prénom, un genre et un
I
niveau
ELH
U
L MO
f E
c hre
c A

Avril 2018 77 / 124


Héritage Héritage simple

C++
Exemple

Un enseignant a un numéro, un nom, un prénom, un genre et un salaire

c

Un étudiant a aussi un numéro, un nom, un prénom, un genre et un
I
niveau
E LH
U
MOsont une sorte de personne
Sémantiquement, enseignant et étudiant
L
h r e fE
A c
c

Avril 2018 77 / 124


Héritage Héritage simple

C++
Exemple

Un enseignant a un numéro, un nom, un prénom, un genre et un salaire

c
Un étudiant a aussi un numéro, un nom, un prénom, un genre et un
I
niveau
E L H
U
MOsont une sorte de personne
Sémantiquement, enseignant et étudiant
L
r e fE
En plus, les deux partagent
h plusieurs attributs tels que numéro, nom,
c
c A
prénom et genre

Avril 2018 77 / 124


Héritage Héritage simple

C++
Exemple

Un enseignant a un numéro, un nom, un prénom, un genre et un salaire

c
Un étudiant a aussi un numéro, un nom, un prénom, un genre et un
I
niveau
E L H
U
MOsont une sorte de personne
Sémantiquement, enseignant et étudiant
L
r e fE
En plus, les deux partagent
h plusieurs attributs tels que numéro, nom,
c
c A
prénom et genre

Donc, on peut peut utiliser la classe Personne puisqu’elle contient tous
les attributs numéro, nom, prénom et genre

Avril 2018 77 / 124


Héritage Héritage simple

C++
Exemple

Un enseignant a un numéro, un nom, un prénom, un genre et un salaire

c
Un étudiant a aussi un numéro, un nom, un prénom, un genre et un
I
niveau
E L H
U
MOsont une sorte de personne
Sémantiquement, enseignant et étudiant
L
r e fE
En plus, les deux partagent
h plusieurs attributs tels que numéro, nom,
c
c A
prénom et genre

Donc, on peut peut utiliser la classe Personne puisqu’elle contient tous
les attributs numéro, nom, prénom et genre

Les classes Étudiant et Enseignant hériteront donc de la classe


Personne

Avril 2018 77 / 124


Héritage Héritage simple

C++
Contenu de Etudiant.h Contenu de Enseignant.h

#ifndef ETUDIANT_H_INCLUDED #ifndef ENSEIGNANT_H_INCLUDED


#define ETUDIANT_H_INCLUDED #define ENSEIGNANT_H_INCLUDED

#include "Personne.h" #include "Personne.h"

I c

class Etudiant : public Personne
{
ELH
class Enseignant : public Personne
{
U
MO
public: public:

f
string getNiveau() const;
E L
void setNiveau(string niveau); void setSalaire(int num);
int getSalaire() const;

private :
A c hre private :

}; c

string niveau;
};
int salaire;

#endif // ETUDIANT_H_INCLUDED #endif // ENSEIGNANT_H_INCLUDED

Avril 2018 78 / 124


Héritage Héritage simple

C++
Contenu de Etudiant.h Contenu de Enseignant.h

#ifndef ETUDIANT_H_INCLUDED #ifndef ENSEIGNANT_H_INCLUDED


#define ETUDIANT_H_INCLUDED #define ENSEIGNANT_H_INCLUDED

#include "Personne.h" #include "Personne.h"

I c

class Etudiant : public Personne
{
ELH
class Enseignant : public Personne
{
U
MO
public: public:
void setNiveau(string niveau);
string getNiveau() const;
f E L void setSalaire(int num);
int getSalaire() const;

private :
A c hre private :

}; c

string niveau;
};
int salaire;

#endif // ETUDIANT_H_INCLUDED #endif // ENSEIGNANT_H_INCLUDED

Remarque

class A : public B permet d’indiquer que la classe A hérite de la classe B

Avril 2018 78 / 124


Héritage Héritage simple

Contenu de Etudiant.h
#include "Etudiant.h"

void Etudiant::setNiveau(string niveau)


{
this->niveau = niveau;
}
string Etudiant::getNiveau() const
{
I c

return niveau;
ELH
}
U
L MO
f E
c hre
c A

Avril 2018 79 / 124


Héritage Héritage simple

Contenu de Etudiant.h
#include "Etudiant.h"

void Etudiant::setNiveau(string niveau)


{
this->niveau = niveau;
}
string Etudiant::getNiveau() const
{
I c

return niveau;
ELH
}
U
L MO
Contenu de Enseignant.cpp
f E
c
#include "Enseignant.h" hre
c A

void Enseignant::setSalaire(int salaire)
{
this->salaire = salaire;
}
int Enseignant::getSalaire() const
{
return salaire;
}

Avril 2018 79 / 124


Héritage Héritage simple

C++
Pour créer un objet de type Enseignant dans le main
Enseignant enseignant;
enseignant.setNom("wick");
enseignant.setSalaire(1700);
cout << enseignant.getNom() << " " << enseignant.getSalaire()
<< endl;
I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 80 / 124


Héritage Héritage simple

C++
Pour créer un objet de type Enseignant dans le main
Enseignant enseignant;
enseignant.setNom("wick");
enseignant.setSalaire(1700);
cout << enseignant.getNom() << " " << enseignant.getSalaire()
<< endl;
I c

ELH
U
Remarque
L MO
re f E
h
N’oublions pas #include "Enseignant.h"
c
c A

Avril 2018 80 / 124


Héritage Héritage simple

C++
Pour créer un objet de type Enseignant dans le main
Enseignant enseignant;
enseignant.setNom("wick");
enseignant.setSalaire(1700);
cout << enseignant.getNom() << " " << enseignant.getSalaire()
<< endl;
I c

ELH
U
Remarque
L MO
re f E
h
N’oublions pas #include "Enseignant.h"
c
c A
En exécutant, le résultat est :
wick 1700

Avril 2018 80 / 124


Héritage Héritage simple

C++
Pour créer un objet de type Enseignant dans le main
Enseignant enseignant;
enseignant.setNom("wick");
enseignant.setSalaire(1700);
cout << enseignant.getNom() << " " << enseignant.getSalaire()
<< endl;
I c

ELH
U
Remarque
L MO
re f E
h
N’oublions pas #include "Enseignant.h"
c
c A
En exécutant, le résultat est :
wick 1700

Refaire la même chose pour Etudiant


Avril 2018 80 / 124
Héritage Héritage simple

C++
Question

Et si on veut utiliser un constructeur à plusieurs paramètres ?

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 81 / 124


Héritage Héritage simple

C++
Question

Et si on veut utiliser un constructeur à plusieurs paramètres ?

Il faut le définir dans Etudiant.h

I c

ELH
Etudiant(int numero, string nom, string prenom, char genre, string
niveau);
U
L MO
f E
c hre
c A

Avril 2018 81 / 124


Héritage Héritage simple

C++
Question

Et si on veut utiliser un constructeur à plusieurs paramètres ?

Il faut le définir dans Etudiant.h

I c

ELH
Etudiant(int numero, string nom, string prenom, char genre, string
niveau);
U
L MO
Ensuite l’implémenter dans Etudiant.cpp (on utilise le constructeur de la classe mère)
f E
hre
Etudiant::Etudiant(int numero, string nom, string prenom, char genre,
c
string niveau) : Personne(numero, nom, prenom, genre), niveau(niveau

{
)
c A

}

Avril 2018 81 / 124


Héritage Héritage simple

C++
Question

Et si on veut utiliser un constructeur à plusieurs paramètres ?

Il faut le définir dans Etudiant.h

I c

ELH
Etudiant(int numero, string nom, string prenom, char genre, string
niveau);
U
L MO
Ensuite l’implémenter dans Etudiant.cpp (on utilise le constructeur de la classe mère)
f E
hre
Etudiant::Etudiant(int numero, string nom, string prenom, char genre,
c
string niveau) : Personne(numero, nom, prenom, genre), niveau(niveau

{
)
c A

}

Enfin, on peut l’appeler (dans le main par exemple)


Etudiant etudiant(100, "green", "steven", ’M’, "licence");
cout << etudiant.getNom() << " " << etudiant.getNiveau() << endl;

Avril 2018 81 / 124


Héritage Héritage simple

C++

À partir de la classe Etudiant

I c
H
On ne peut avoir accès direct à un attribut de la classe mère
EcarLles attributs ont une
U
MO
C’est-à-dire, on ne peut faire this->num
visibilité private L
fd’unEattribut privé de la classe mère, il faut
Pour modifier la valeur
c h r e
c A
les getters/setters
soit utiliser
soit mettre la visibilité des attributs de la classe mère à protected

Avril 2018 82 / 124


Héritage Héritage multiple

C++

Particularité du C++ I c

H
L ément de
Esimultan
U
Héritage multiple : une classe peut hériter
plusieurs autres
L MO
h r e
L’héritage multiple est f E é par le langage C++
autoris
A c
c

Avril 2018 83 / 124


Héritage Héritage multiple

C++
Considérons la classe Doctorant qui hérite de Enseignant et Etudiant
#ifndef DOCTORANT_H_INCLUDED
#define DOCTORANT_H_INCLUDED

#include "Enseignant.h"
I c
#include "Etudiant.h"
L H
EEnseignant
OU
class Doctorant : public Etudiant, public
{
L M
public:
r e E nom, string prenom, char genre
f string
, stringA h
Doctorant(int numero,
c int salaire, int annee);
niveau,
c
void setAnnee(int anne);
int getAnnee() const;

private:
int annee;
};
#endif // DOCTORANT_H_INCLUDED

Avril 2018 84 / 124


Héritage Héritage multiple

C++
Le fichier Doctorant.cpp
#include "Doctorant.h"
#include "Enseignant.h"
#include "Etudiant.h"

c

Doctorant::Doctorant(int numero, string nom, string prenom, char genre,
I
string niveau, int salaire, int annee) :

ELH
Enseignant(numero, nom, prenom, genre, salaire),
U
MO
Etudiant(numero, nom, prenom, genre, niveau),
annee(annee)
{
f E L
hre
}

c
{ c A
void Doctorant::setAnnee(int annee)

this->annee = annee;
}

int Doctorant::getAnnee() const


{
return annee;
}

Avril 2018 85 / 124


Héritage Héritage multiple

C++
Essayons de créer un objet de type Doctorant dans le main
int main()
{
Doctorant doctorant(100, "wick", "john", ’M’, "doctorat",
1700, 1);
I c

cout << doctorant.getNom() << endl;
cout << doctorant.getNiveau() << endl;
ELH
U
MO
cout << doctorant.getSalaire() << endl;

f E L
cout << doctorant.getAnnee() << endl;

hre
}

c
c A

Avril 2018 86 / 124


Héritage Héritage multiple

C++
Essayons de créer un objet de type Doctorant dans le main
int main()
{
Doctorant doctorant(100, "wick", "john", ’M’, "doctorat",
1700, 1);
I c

cout << doctorant.getNom() << endl;
cout << doctorant.getNiveau() << endl;
ELH
U
MO
cout << doctorant.getSalaire() << endl;

f E L
cout << doctorant.getAnnee() << endl;

hre
}

c
c A

Erreur à l’exécution : problème d’ambiguı̈té

la méthode getNom() est définie dans Etudiant

et elle est aussi définie dans Enseignant

Avril 2018 86 / 124


Héritage Héritage multiple

C++
Pour résoudre ce problème, on peut préciser une base valide (soit Etudiant
soit Enseignant)
int main()
{

c

Doctorant doctorant(100, "wick", "john", ’M’, "doctorat",
I
1700, 1);
cout << doctorant.Etudiant::getNom() << endl;
ELH
U
MO
cout << doctorant.getNiveau() << endl;

f E L
cout << doctorant.getSalaire() << endl;
cout << doctorant.getAnnee() << endl;
}
c hre
c A

Avril 2018 87 / 124


Héritage Héritage multiple

C++
Pour résoudre ce problème, on peut préciser une base valide (soit Etudiant
soit Enseignant)
int main()
{

c

Doctorant doctorant(100, "wick", "john", ’M’, "doctorat",
I
1700, 1);
cout << doctorant.Etudiant::getNom() << endl;
ELH
U
MO
cout << doctorant.getNiveau() << endl;

f E L
cout << doctorant.getSalaire() << endl;
cout << doctorant.getAnnee() << endl;
}
c hre
c A

Le résultat est :
wick
doctorat
1700
1

Avril 2018 87 / 124


Héritage Héritage multiple

C++
Revenant au constructeur de Doctorant qui est redondant : certaines données sont
passées à la fois à Etudiant() et à Enseignant()
Doctorant::Doctorant(int numero, string nom, string prenom, char genre,
string niveau, int salaire, int annee) :
Enseignant(numero, nom, prenom, genre, salaire),
Etudiant(numero, nom, prenom, genre, niveau),
I c

{
annee(annee)

ELH
U
MO
}

f E L
c hre
c A

Avril 2018 88 / 124


Héritage Héritage multiple

C++
Revenant au constructeur de Doctorant qui est redondant : certaines données sont
passées à la fois à Etudiant() et à Enseignant()
Doctorant::Doctorant(int numero, string nom, string prenom, char genre,
string niveau, int salaire, int annee) :
Enseignant(numero, nom, prenom, genre, salaire),
Etudiant(numero, nom, prenom, genre, niveau),
I c

{
annee(annee)

ELH
U
MO
}

f E L
hre
Une solution consiste à faire
c
c A
Doctorant::Doctorant(int numero, string nom, string prenom, char genre,

string niveau, int salaire, int annee) :
Enseignant(numero, nom, prenom, genre, salaire),
Etudiant(niveau),
annee(annee)
{
}

Avril 2018 88 / 124


Héritage Héritage multiple

C++
Revenant au constructeur de Doctorant qui est redondant : certaines données sont
passées à la fois à Etudiant() et à Enseignant()
Doctorant::Doctorant(int numero, string nom, string prenom, char genre,
string niveau, int salaire, int annee) :
Enseignant(numero, nom, prenom, genre, salaire),
Etudiant(numero, nom, prenom, genre, niveau),
I c

{
annee(annee)

ELH
U
MO
}

f E L
hre
Une solution consiste à faire
c
c A
Doctorant::Doctorant(int numero, string nom, string prenom, char genre,

string niveau, int salaire, int annee) :
Enseignant(numero, nom, prenom, genre, salaire),
Etudiant(niveau),
annee(annee)
{
}
N’oublions pas de déclarer et implémenter ce nouveau constructeur avec un paramètre dans
Etudiant
Avril 2018 88 / 124
Héritage Mode de visibilité

C++

Forme générale
class ClasseFille : modeDeVisivility ClasseMère
{
// code
I c

};
ELH
U
L MO
f E
chre
c A

Avril 2018 89 / 124


Héritage Mode de visibilité

C++

Forme générale
class ClasseFille : modeDeVisivility ClasseMère
{
// code
I c

};
ELH
U
L MO
f E
c hre
c A
Trois modes de visibilité

public
private (par défaut)
protected

Avril 2018 89 / 124


Héritage Mode de visibilité

Exemple
class A
{
public: int x;
protected: int y;
private: int z;
};
class B : public A
{
I c

// x est public
ELH
// y est protected
U
};
// z n’est pas accessible de B
L MO
f E
hre
class C : protected A
{
c
c A
// x est protected

// y est protected
// z n’est pas accessible de C
};
class D : private A
{
// x est private
// y est private
// z n’est pas accessible de D
};
Avril 2018 90 / 124
Polymorphisme Surcharge

C++

Surcharge (overload)

Définir dans une classe plusieurs méthodes avec


I c

le même nom
ELH
U
une signature différente
L MO
f E
hre
Possible avec le C++
c
c A

Le meilleur exemple : les constructeurs (qui sont des méthodes
particulières) qu’on a définis avec et sans paramètre dans une
même classe (évidemment avec le même nom)

Avril 2018 91 / 124


Polymorphisme Redéfinition

C++
Redéfinition (override)

Définir une méthode dans une classe qui est déjà définie dans la classe mère

Possible aussi avec le C++

I c
Deux manières de redéfinir une méthode
EL H
O
Proposer une nouvelle implémentation U dans la classe fille différente
et indépendante de celle de laM
définit une nouvelle f E L classe mère (simple comme si on

h r e méthode)
c nouvelle implémentation qui fait référence à celle de
c Amère
Proposer une
la
classe

Avril 2018 92 / 124


Polymorphisme Redéfinition

C++
Redéfinition (override)

Définir une méthode dans une classe qui est déjà définie dans la classe mère

Possible aussi avec le C++

I c
Deux manières de redéfinir une méthode
EL H
O
Proposer une nouvelle implémentation U dans la classe fille différente
et indépendante de celle de laM
définit une nouvelle f E L classe mère (simple comme si on

h r e méthode)
c nouvelle implémentation qui fait référence à celle de
c Amère
Proposer une
la
classe

Exemple

Redéfinir la méthode afficherDetails() dans la classe Etudiant : une fois sans


faire référence à celle de la classe Personne et une autre en faisant référence.

Avril 2018 92 / 124


Polymorphisme Redéfinition

C++
Il faut commencer par la définir dans Etudiant.h
void afficherDetails() const;

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 93 / 124


Polymorphisme Redéfinition

C++
Il faut commencer par la définir dans Etudiant.h
void afficherDetails() const;

Ensuite l’implémenter dans Etudiant.cpp

I c

void Etudiant::afficherDetails() const
{
ELH
U
MO
cout num << " "<< nom << " " ;
cout prenom << " "<< genre << endl;
cout << niveau << endl;
f E L
hre
}

c
c A

Avril 2018 93 / 124


Polymorphisme Redéfinition

C++
Il faut commencer par la définir dans Etudiant.h
void afficherDetails() const;

Ensuite l’implémenter dans Etudiant.cpp

I c

void Etudiant::afficherDetails() const
{
ELH
U
MO
cout num << " "<< nom << " " ;
cout prenom << " "<< genre << endl;
cout << niveau << endl;
f E L
hre
}

c
c A

Enfin, on peut l’appeler (dans le main)
Etudiant etudiant(100, "green" , "steven", ’M’, "licence");
etudiant.afficherDetails();
/* affiche
100 steven green M
licence
*/

Avril 2018 93 / 124


Polymorphisme Redéfinition

C++
On peut aussi utiliser l’implémentation de la classe Personne
void Etudiant::afficherDetails() const
{
Personne::afficherDetails();
cout << " " << niveau << endl;
I c

}
ELH
U
L MO
f E
c hre
c A

Avril 2018 94 / 124


Polymorphisme Redéfinition

C++
On peut aussi utiliser l’implémentation de la classe Personne
void Etudiant::afficherDetails() const
{
Personne::afficherDetails();
cout << " " << niveau << endl;
I c

}
ELH
U
En testant, le résultat est le même
L MO
f E
hre
Etudiant etudiant(100, "green", "steven", ’M’, "licence");
c
etudiant.afficherDetails();
/* affiche
c A

100 steven green M
licence
*/

Avril 2018 94 / 124


Polymorphisme Redéfinition

C++
On peut aussi utiliser l’implémentation de la classe Personne
void Etudiant::afficherDetails() const
{
Personne::afficherDetails();
cout << " " << niveau << endl;
I c

}
ELH
U
En testant, le résultat est le même
L MO
f E
hre
Etudiant etudiant(100, "green", "steven", ’M’, "licence");
c
etudiant.afficherDetails();
/* affiche
c A

100 steven green M
licence
*/

Refaire la même chose pour Enseignant

Avril 2018 94 / 124


Polymorphisme Méthode virtuelle

C++
Dans main.cpp, créons une fonction afficher(Personne p) qui prend en paramètre un
objet Personne et ensuite appelle sa méthode afficherDetails()

void afficher(Personne p) {
p.afficherDetails();
}

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 95 / 124


Polymorphisme Méthode virtuelle

C++
Dans main.cpp, créons une fonction afficher(Personne p) qui prend en paramètre un
objet Personne et ensuite appelle sa méthode afficherDetails()

void afficher(Personne p) {
p.afficherDetails();
}

I c

ELH
U
Créons ensuite trois objets de type Personne, Enseignant et Etudiant et appelons
chaque fois la fonction afficher()
L MO
f E
hre
Personne personne(101, "dalton", "jack", ’M’);
afficher(personne);
c
c A
Enseignant enseignant;


enseignant.setNum(100);
enseignant.setNom("wick");
enseignant.setPrenom("john");
enseignant.setGenre(’M’);
enseignant.setSalaire(1700);
afficher(enseignant);
Etudiant etudiant(100, "green", "steven", ’M’, "licence");
afficher(etudiant);

Avril 2018 95 / 124


Polymorphisme Méthode virtuelle

C++
Le résultat attendu est
101 jack dalton M
100 john wick M
1700
102 steven green M
I c

licence
ELH
U
L MO
f E
c hre
c A

Avril 2018 96 / 124


Polymorphisme Méthode virtuelle

C++
Le résultat attendu est
101 jack dalton M
100 john wick M
1700
102 steven green M
I c

licence
ELH
U
L MO
f E
e obtenu est
Mais, en exécutant, le rrésultat
A Mc h
101 jack c
dalton
100 john wick M
102 steven green M

Avril 2018 96 / 124


Polymorphisme Méthode virtuelle

C++
Le résultat attendu est
101 jack dalton M
100 john wick M
1700
102 steven green M
I c

licence
ELH
U
L MO
f E
e obtenu est
Mais, en exécutant, le rrésultat
A Mc h
101 jack c
dalton
100 john wick M
102 steven green M

C’est ce qu’on appelle les liens statiques.


Avril 2018 96 / 124
Polymorphisme Méthode virtuelle

C++

I c
Solution : méthodes virtuelles
E L H
U
MO et
Déclarer ces méthodes comme virtuelle,
L
h r f Ela fonction afficher()
Utiliser une référenceedans
A c
c

Avril 2018 97 / 124


Polymorphisme Méthode virtuelle

C++
Dans Personne.h, déclarer afficherDetails() comme méthode virtuelle
virtual void afficherDetails() const;

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 98 / 124


Polymorphisme Méthode virtuelle

C++
Dans Personne.h, déclarer afficherDetails() comme méthode virtuelle
virtual void afficherDetails() const;

I c
Remarques
E LH
O U
L M
Par définition d’héritage, les méthodes afficherDetails() redéfinies dans

fsi E
Etudiant et Enseignant sont aussi virtuelles

c
Il est possible de le prh r e
éciser on a peur d’oublier

c A

Avril 2018 98 / 124


Polymorphisme Méthode virtuelle

C++
Dans Personne.h, déclarer afficherDetails() comme méthode virtuelle
virtual void afficherDetails() const;

I c
Remarques
E LH
O U
L M
Par définition d’héritage, les méthodes afficherDetails() redéfinies dans

fsi E
Etudiant et Enseignant sont aussi virtuelles

c
Il est possible de le prh r e
éciser on a peur d’oublier

c A
Utiliser une référence dans la fonction afficher()
void afficher(Personne const& p) {
p.afficherDetails();
}

Avril 2018 98 / 124


Polymorphisme Méthode virtuelle

C++

En exécutant maintenant, le résultat est


I c

101 jack dalton M
ELH
U
100 john wick M
L MO
1700
f E
102 steven green M
c hre
c A
licence

Avril 2018 99 / 124


Polymorphisme Méthode virtuelle pure

C++

Hypothèse et problématique

On voudrait définir une méthode getStatutAcademique() qui


retourne
I c
H
le grade d’un enseignant compte tenu de son salaire
L niveau
Eson
U
le niveau d’expérience d’un étudiant selon
O
L M
f E cette méthode ne fait rien
Pour un objet de type Personne,
r e
A ch
c

Avril 2018 100 / 124


Polymorphisme Méthode virtuelle pure

C++

Hypothèse et problématique

On voudrait définir une méthode getStatutAcademique() qui


retourne
I c
H
le grade d’un enseignant compte tenu de son salaire
L niveau
Eson
U
le niveau d’expérience d’un étudiant selon
O
L M
f E cette méthode ne fait rien
Pour un objet de type Personne,
r e
A ch
c
Solution : méthode virtuelle pure

une méthode virtuelle sans code dans la classe mère


elle est seulement initialisée à zéro

Avril 2018 100 / 124


Polymorphisme Méthode virtuelle pure

C++

I c

Dans Personne.h, on déclare cette nouvelle méthode
H
ELconst = 0;
U
virtual string getStatutAcademique()

L MO
h r e fE
A c
c

Avril 2018 101 / 124


Polymorphisme Méthode virtuelle pure

C++

I c

Dans Personne.h, on déclare cette nouvelle méthode
H
ELconst = 0;
virtual string getStatutAcademique()
U
L MO
h r e fE
A c à faire dans Personne.cpp
Aucune implémentation
c

Avril 2018 101 / 124


Polymorphisme Méthode virtuelle pure

C++
Dans Etudiant.h et Enseignant.h, déclarer getStatutAcademique()

virtual string getStatutAcademique() const;

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 102 / 124


Polymorphisme Méthode virtuelle pure

C++
Dans Etudiant.h et Enseignant.h, déclarer getStatutAcademique()

virtual string getStatutAcademique() const;

I c

H
Et voici l’implémentation à ajouter dans Etudiant.cpp

EL
string Etudiant::getStatutAcademique() const
U
{
L MO
E
return niveau == "licence" ? "debutant" : "junior";
f
hre
}

c
c A

Avril 2018 102 / 124


Polymorphisme Méthode virtuelle pure

C++
Dans Etudiant.h et Enseignant.h, déclarer getStatutAcademique()

virtual string getStatutAcademique() const;

I c

H
Et voici l’implémentation à ajouter dans Etudiant.cpp

EL
string Etudiant::getStatutAcademique() const
U
{
L MO
E
return niveau == "licence" ? "debutant" : "junior";
f
hre
}

c
c A

Et voici l’implémentation à ajouter dans Enseignant.cpp

string Enseignant::getStatutAcademique() const


{
return salaire > 3000 ? "MCF" : "PR";
}

Avril 2018 102 / 124


Polymorphisme Méthode virtuelle pure

C++

Pour tester, voici le code à mettre dans le main


Personne personne(100, "wick", "john", ’M’);
I c

ELH
cout << personne.getStatutAcademique() << endl;
U
L MO
f E
c hre
c A

Avril 2018 103 / 124


Polymorphisme Méthode virtuelle pure

C++

Pour tester, voici le code à mettre dans le main


Personne personne(100, "wick", "john", ’M’);
I c

cout << personne.getStatutAcademique() << endl;
ELH
U
L MO
f E
A c
Erreur à l’exécution hre
c
la classe Personne est maintenant abstraite.

Avril 2018 103 / 124


Classe abstraite

C++

Classe abstraite

I c
C’est une classe contenant au moins une méthode virtuelle pure
EL H
U
C’est une classe qu’on ne peut instancier

L MO
e fE
Les classes filles d’une classe
méthodes virtuellesrpures
h
abstraite doivent implémenter ses

A c d’une classe abstraite peuvent implémenter ses


c
Les classes filles
méthodes virtuelles

Avril 2018 104 / 124


Interface

C++

Interface I c
H
L virtuelles pures
Esont
U
C’est une classe dont toutes les méthodes
L MlaO
Pas de mot clé interface
re f E pour création d’une interface en
C++
c h
c A

Avril 2018 105 / 124


Opérateur

C++

Opérateur
I c

LH
C++ nous offre la possibilité de surcharger les opérateurs
E
arithmétiques : +, -, *, /, %, =, +=, O U
L M ++...
ou de comparaison : ==,
r e f E!=, >=, <=...
A
Il est possible chdéfinir comment utiliser ces opérateurs entre
de
c
deux objets

Avril 2018 106 / 124


Opérateur

C++
Considérons la classe Note suivante définie dans Note.h
#ifndef NOTE_H_INCLUDED
#define NOTE_H_INCLUDED

class Note {
I c

public: H
E=L0);
O U
Note(float valeur = 0, int coefficient
float getValeur() const;
L M
E
fvaleur);
int getCoefficient() const;
r e
A h
void setValeur(float
c
void setCoefficient(int coefficient);

private:
c
float valeur;
int coefficient;
};

#endif // NOTE_H_INCLUDED

Avril 2018 107 / 124


Opérateur

C++
L’implémentation dans Note.cpp
Note::Note(float valeur, int coefficient): valeur(valeur), coefficient(
coefficient)
{

}
I c

float Note::getValeur() const
{
ELH
U
MO
return valeur;
}

E
int Note::getCoefficient() const
f L
hre
{

c
return coefficient;
}
c A

void Note::setValeur(float valeur)
{
this->valeur = valeur;
}
void Note::setCoefficient(int coefficient)
{
this->coefficient = coefficient;
}

Avril 2018 108 / 124


Opérateur

C++

Nous voudrons surcharger l’opérateur == pour pouvoir comparer deux coefficients de


deux objets de type Note comme le montre l’exemple suivant

#include <iostream>
#include "Note.h"
I c

using namespace std;

ELH
U
MO
int main()
{
Note note1(12, 2);
f E L
hre
Note note2(15, 3);
Note note3(12, 3);
c
c A
string b1 = note1 == note2 ? "note1 == note2" : "note1 != note2";

string b2 = note2 == note3 ? "note2 == note3" : "note2 != note3";
cout << b1 << endl;
cout << b2 << endl;
return 0;
}

Avril 2018 109 / 124


Opérateur

Pour cela, commençons par définir le prototype de notre opérateur dans Note.h
#ifndef NOTE_H_INCLUDED
#define NOTE_H_INCLUDED

class Note {
public:
Note(float valeur = 0, int coefficient = 0);
float getValeur() const;
int getCoefficient() const;
I c

void setValeur(float valeur);
ELH
void setCoefficient(int coefficient);
U
bool operator == (Note const& obj1);
private:
L MO
float valeur;
f E
int coefficient;
c hre
c A
};


#endif // NOTE_H_INCLUDED

Avril 2018 110 / 124


Opérateur

Pour cela, commençons par définir le prototype de notre opérateur dans Note.h
#ifndef NOTE_H_INCLUDED
#define NOTE_H_INCLUDED

class Note {
public:
Note(float valeur = 0, int coefficient = 0);
float getValeur() const;
int getCoefficient() const;
I c

void setValeur(float valeur);
ELH
void setCoefficient(int coefficient);
U
bool operator == (Note const& obj1);
private:
L MO
float valeur;
f E
int coefficient;
c hre
c A
};


#endif // NOTE_H_INCLUDED

Implémentons le prototype précédent dans Note.h


bool Note::operator == (Note const& obj1)
{
return coefficient == obj1.getCoefficient();
}

Avril 2018 110 / 124


Opérateur

C++

I c

EL
En testant le code précédent, le résultat estH
U
note1 != note2
L MO
note2 == note3
f E
c hre
c A

Avril 2018 111 / 124


Opérateur

C++

Exercice

I
Étant donnés deux objets note1 et note2 de type Note c
LH
Eretourner
Implémenter l’opérateur + qui permettra
O U de un objet de
L
type Note dont la valeur = valeur1M + valeur2 et le coefficient

h r e f leEcoefficient
= coefficient1 (ou coefficient12) si les deux notes sont égales, -1

A c
pour la valeur et -1 pour sinon.

valeur1 c et coefficient1 (respectivement valeur2 et
coefficient2) désignent les attributs de note1 (resp. note2)

Avril 2018 112 / 124


Opérateur

C++
Commençons par déclarer le nouvel opérateur dans Note.h

#ifndef NOTE_H_INCLUDED
#define NOTE_H_INCLUDED

class Note {
I c

public:
Note(float valeur = 0, int coefficient = 0);
ELH
U
MO
float getValeur() const;
int getCoefficient() const;

f E
void setValeur(float valeur);L
hre
void setCoefficient(int coefficient);
c
c A
bool operator == (Note const& obj1);

private:
Note operator + (Note const& obj1);

float valeur;
int coefficient;
};

#endif // NOTE_H_INCLUDED

Avril 2018 113 / 124


Opérateur

C++

Implémentons cet opérateur dans Note.cpp


Note Note::operator + (Note const& obj1)
I c

{
ELH
Note note(-1, -1);
U
if (*this == obj1) {
L MO
f E
note.setValeur(obj1.getValeur() + valeur);
c hre
note.setCoefficient(coefficient);
}
c A

return note;
}

Avril 2018 114 / 124


Opérateur

C++
Pour tester
#include <iostream>
#include "Note.h"
using namespace std;

int main()
{
I c

Note note1(12, 2);
ELH
Note note2(15, 3);
U
Note note3(12, 3);
Note note4 = note1 + note2;
L MO
f E
hre
Note note5 = note2 + note3;

c
cout << note4.getValeur() << " " << note4.getCoefficient() << endl;

c A
cout << note5.getValeur() << " " << note5.getCoefficient() << endl;

}
return 0;

Avril 2018 115 / 124


Opérateur

C++
Pour tester
#include <iostream>
#include "Note.h"
using namespace std;

int main()
{
I c

Note note1(12, 2);
ELH
Note note2(15, 3);
U
Note note3(12, 3);
Note note4 = note1 + note2;
L MO
f E
hre
Note note5 = note2 + note3;

c
cout << note4.getValeur() << " " << note4.getCoefficient() << endl;

c A
cout << note5.getValeur() << " " << note5.getCoefficient() << endl;

}
return 0;

Le résultat est
-1 -1
27 3
Avril 2018 115 / 124
Opérateur

C++
Définir l’opérateur += dans Personne qui nous permettra d’exécuter le code suivant
int main()
{
Personne personne4(102, "jordan", "mike", ’M’);
Adresse a1 ("paradis", "13015", "Marseille");
personne4 += a1;
I c

Adresse a2 ("pasteur", "69200", "Lyon");
personne4 += a2;
ELH
U
MO
cout << personne4.getNom() << " " ;
cout << personne4.getPrenom() << endl;
for(int i =0; i < 2; i++)
f E L
hre
{

c
cout << personne4.getAdresses()[i].getCodePostal() << endl;

}
}
c A

Avril 2018 116 / 124


Opérateur

C++
Définir l’opérateur += dans Personne qui nous permettra d’exécuter le code suivant
int main()
{
Personne personne4(102, "jordan", "mike", ’M’);
Adresse a1 ("paradis", "13015", "Marseille");
personne4 += a1;
I c

Adresse a2 ("pasteur", "69200", "Lyon");
personne4 += a2;
ELH
U
MO
cout << personne4.getNom() << " " ;
cout << personne4.getPrenom() << endl;
for(int i =0; i < 2; i++)
f E L
hre
{

c
cout << personne4.getAdresses()[i].getCodePostal() << endl;

}
}
c A

En exécutant, le résultat est

13015
69200

Avril 2018 116 / 124


Opérateur

C++
Commençons par définir un attribut privé indice dans Personne.h
private:
int indice = 0;

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 117 / 124


Opérateur

C++
Commençons par définir un attribut privé indice dans Personne.h
private:
int indice = 0;

I c

EL H
Définissons l’opérateur dans Personne.h
U
void operator += (Adresse const&
L MOadresse);
h r e fE
A c
c

Avril 2018 117 / 124


Opérateur

C++
Commençons par définir un attribut privé indice dans Personne.h
private:
int indice = 0;

I c

EL H
Définissons l’opérateur dans Personne.h
U
void operator += (Adresse const&
L MOadresse);
h r e fE
A c
c
érateur dans Personne.cpp
Implémentons cet op
void Personne::operator += (Adresse const& adresse)
{
adresses[indice] = adresse;
indice++;
}

Avril 2018 117 / 124


Opérateur

C++
En exécutant le main précédent
#include <iostream>
#include "Note.h"
using namespace std;

int main()
{
I c

Note note1(12, 2);
ELH
Note note2(15, 3);
U
Note note3(12, 3);
Note note4 = note1 + note2;
L MO
f E
hre
Note note5 = note2 + note3;

c
cout << note4.getValeur() << " " << note4.getCoefficient() << endl;

c A
cout << note5.getValeur() << " " << note5.getCoefficient() << endl;

}
return 0;

Avril 2018 118 / 124


Opérateur

C++
En exécutant le main précédent
#include <iostream>
#include "Note.h"
using namespace std;

int main()
{
I c

Note note1(12, 2);
ELH
Note note2(15, 3);
U
Note note3(12, 3);
Note note4 = note1 + note2;
L MO
f E
hre
Note note5 = note2 + note3;

c
cout << note4.getValeur() << " " << note4.getCoefficient() << endl;

c A
cout << note5.getValeur() << " " << note5.getCoefficient() << endl;

}
return 0;

Le résultat est
-1 -1
27 3
Avril 2018 118 / 124
Énumération

C++
Énumération

Ensemble de constante

Commençant par défaut de 0


I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 119 / 124


Énumération

C++
Énumération

Ensemble de constante

Commençant par défaut de 0


I c
E LH
U
MO et avant la fonction
Déclarons une énumération (dans main.cpp
L
fE
main())
enum mois { JANVIER,
h r eFEVRIER, MARS, AVRIL, MAI, JUIN,
c SEPTEMBRE, OCTOBRE, NOVEMBRE, DECEMBRE
JUILLET, AOUT,
}; c A

Avril 2018 119 / 124


Énumération

C++
Énumération

Ensemble de constante

Commençant par défaut de 0


I c
E LH
U
MO et avant la fonction
Déclarons une énumération (dans main.cpp
L
fE
main())
enum mois { JANVIER,
h r eFEVRIER, MARS, AVRIL, MAI, JUIN,
c SEPTEMBRE, OCTOBRE, NOVEMBRE, DECEMBRE
JUILLET, AOUT,
}; c A
Pour récupérer un élément
cout << JANVIER << endl;
// affiche 0

Avril 2018 119 / 124


Énumération

C++
Pour éviter un éventuel conflit avec une autre énumération, on peut faire
cout << mois::JANVIER << endl;
// affiche 0

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 120 / 124


Énumération

C++
Pour éviter un éventuel conflit avec une autre énumération, on peut faire
cout << mois::JANVIER << endl;
// affiche 0

I c

EL H
Pour modifier l’indice du premier élément
U
OMARS, AVRIL, MAI, JUIN,
enum mois { JANVIER = 1, FEVRIER,
L M
e f
JUILLET, AOUT, SEPTEMBRE,
r E OCTOBRE, NOVEMBRE, DECEMBRE
};
A ch
c

Avril 2018 120 / 124


Énumération

C++
Pour éviter un éventuel conflit avec une autre énumération, on peut faire
cout << mois::JANVIER << endl;
// affiche 0

I c

EL H
Pour modifier l’indice du premier élément
U
OMARS, AVRIL, MAI, JUIN,
enum mois { JANVIER = 1, FEVRIER,
L M
e f
JUILLET, AOUT, SEPTEMBRE,
r E OCTOBRE, NOVEMBRE, DECEMBRE
};
A ch
c
En affichant maintenant, le résultat est
cout << mois::JANVIER << endl;
// affiche 1

Avril 2018 120 / 124


Énumération

C++
On peut aussi modifier plusieurs indices simultanément
enum mois { JANVIER = 1, FEVRIER, MARS, AVRIL = 10, MAI, JUIN,
JUILLET, AOUT, SEPTEMBRE, OCTOBRE, NOVEMBRE = 2, DECEMBRE };

I c

ELH
U
L MO
f E
c hre
c A

Avril 2018 121 / 124


Énumération

C++
On peut aussi modifier plusieurs indices simultanément
enum mois { JANVIER = 1, FEVRIER, MARS, AVRIL = 10, MAI, JUIN,
JUILLET, AOUT, SEPTEMBRE, OCTOBRE, NOVEMBRE = 2, DECEMBRE };

I c

En affichant, le résultat est
ELH
U
cout << mois::MARS << endl;
L MO
// affiche 3
f E
hre
cout << mois::JUIN << endl;
// affiche 12
c
c A

cout << mois::DECEMBRE << endl;
// affiche 3

Avril 2018 121 / 124


Énumération

C++
On peut aussi modifier plusieurs indices simultanément
enum mois { JANVIER = 1, FEVRIER, MARS, AVRIL = 10, MAI, JUIN,
JUILLET, AOUT, SEPTEMBRE, OCTOBRE, NOVEMBRE = 2, DECEMBRE };

I c

En affichant, le résultat est
ELH
U
cout << mois::MARS << endl;
L MO
// affiche 3
f E
hre
cout << mois::JUIN << endl;
// affiche 12
c
c A

cout << mois::DECEMBRE << endl;
// affiche 3

Ceci est une erreur, on ne peut modifier une constante


mois::JANVIER = 3;

Avril 2018 121 / 124


struct

C++

struct
I c

ELH
Une classe dont la visibilité par défaut de ses membres (attributs
et méthodes) est public U
L MO
E
Se déclare avec le mot-clé struct
f
c hre
c A
Le mode de visibilité par défaut de l’héritage d’une struct qui

hérite d’une classe est public

Avril 2018 122 / 124


struct

C++
Déclarons une struct appelée Structure dans Structure.h
#ifndef STRUCTURE_H_INCLUDED
#define STRUCTURE_H_INCLUDED

I c

#include <string.h>
ELH
U
struct Structure
L MO
{
f E
int num;
c hre
c A

std::string nom;
char genre;
void afficherDetails();
};

#endif // STRUCTURE_H_INCLUDED

Avril 2018 123 / 124


struct

C++
Implémentons la méthode afficherDetails() dans Structure.cpp
#include <iostream>
#include "Structure.h"

void Structure::afficherDetails()
{
I c

}
ELH
std::cout << num << " " << nom << " " << genre << std::endl;

U
L MO
f E
c hre
c A

Avril 2018 124 / 124


struct

C++
Implémentons la méthode afficherDetails() dans Structure.cpp
#include <iostream>
#include "Structure.h"

void Structure::afficherDetails()
{
I c

}
ELH
std::cout << num << " " << nom << " " << genre << std::endl;

U
L MO
f E
hre
Pour tester
c
c A
int main()
{

Structure first;
first.num = 100;
first.nom = "wick";
first.genre = ’M’;
first.afficherDetails();
// affiche 100 wick M
}

Avril 2018 124 / 124

Vous aimerez peut-être aussi