Explorer les Livres électroniques
Catégories
Explorer les Livres audio
Catégories
Explorer les Magazines
Catégories
Explorer les Documents
Catégories
Achref El Mouelhi
elmouelhi.achref@gmail.com
C++
Qu’est ce qu’une classe en POO ?
C++
Qu’est ce qu’une classe en POO ?
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
C++
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
C++
Particularité du C++ et bonnes pratiques
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
C++
Particularité du C++ et bonnes pratiques
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.
Contenu de Personne.h
#ifndef PERSONNE_H_INCLUDED
#define PERSONNE_H_INCLUDED
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
Contenu de Personne.h
#ifndef PERSONNE_H_INCLUDED
#define PERSONNE_H_INCLUDED
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.
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
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
C++
Code généré de Personne.cpp
I c
ELH
U
L MO
f E
c hre
c A
C++
Code généré de Personne.cpp
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;
C++
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
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
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
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
C++
I c
ELH
U
L MO
f E
c hre
c A
C++
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
C++
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();
C++
C++
C++
Hypothèse
I c
ELH
U
L MO
f E
c hre
c A
C++
Hypothèse
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
C++
Hypothèse
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
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
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
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 }
C++
Utilisons const& dans Personne.h
#ifndef PERSONNE_H_INCLUDED
#define PERSONNE_H_INCLUDED
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;
}
C++
I c
Remarque ELH
U
L
this : pointeur sur l’objet courant MO
f E
c hre
c A
C++
Mettons à jour la fonction principale
#include <iostream>
#include "Personne.h"
C++
Mettons à jour la fonction principale
#include <iostream>
#include "Personne.h"
C++
Testons avec une valeur autre que M ou F
#include <iostream>
#include "Personne.h"
C++
Testons avec une valeur autre que M ou F
#include <iostream>
#include "Personne.h"
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
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)
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;
};
C++
L’implémentation dans Personne.cpp
c A
{
}
return prenom;
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;
}
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;
}
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
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;
};
C++
C++
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);
C++
C++
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;
}
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
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
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
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;
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;
#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;
}
#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;
}
#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;
}
#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;
}
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
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
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
C++
Commençons par définir le constructeur dans Personne.h
I c
ELH
U
L MO
f E
c hre
c A
C++
Commençons par définir le constructeur dans Personne.h
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
C++
Commençons par définir le constructeur dans Personne.h
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
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
C++
C++
Commençons par définir le prototype de ce constructeur dans Personne.h
I c
ELH
U
L MO
f E
c hre
c A
C++
Commençons par définir le prototype de ce constructeur dans Personne.h
{
genre(’M’)
L MO
f E
}
c hre
c A
C++
Commençons par définir le prototype de ce constructeur dans Personne.h
{
genre(’M’)
L MO
f E
}
c hre
c A
Testons ce constructeur dans le main
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
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;
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;
}
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
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
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
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
}
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
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
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
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
L MO
f
int Personne::nbrPersonnes = 0;
E
Personne::Personne()
c hre
{
}
c A
nbrPersonnes++;
C++
C++
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
}
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++
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
C++
Définissons une fonction amie dans Personne.h (& pour pouvoir modifier l’objet)
I c
ELH
U
L MO
f E
c hre
c A
C++
Définissons une fonction amie dans Personne.h (& pour pouvoir modifier l’objet)
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
C++
Définissons une fonction amie dans Personne.h (& pour pouvoir modifier l’objet)
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
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
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
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
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++
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
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
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
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
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
C++
Le fichier Adresse.cpp (partie 1)
#include "Personne.h"
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;
}
C++
Le fichier Adresse.cpp (partie 2)
c A
{
}
return ville;
C++
Importons la classe Adresse dans Personne.h
#include "Adresse.h"
I c
ELH
U
L MO
f E
c hre
c A
C++
Importons la classe Adresse dans Personne.h
#include "Adresse.h"
C++
Importons la classe Adresse dans Personne.h
#include "Adresse.h"
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
I c
ELH
U
L MO
f E
c hre
c A
f E L
c hre
c A
f E L
hre
Implémentons les getter/setter dans Personne.cpp
c
c A
void Personne::setAdresse(Adresse adresse)
{
this->adresse = adresse;
}
C++
Testons cela dans la fonction principale main
#include <iostream>
#include "Personne.h"
hre
cout << personne3.getNom() << " " ;
c
c A
cout << personne3.getPrenom() << " " ;
cout << personne3.getAdresse().getCodePostal() << endl;
return 0;
}
C++
Testons cela dans la fonction principale main
#include <iostream>
#include "Personne.h"
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"
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;
}
C++
Essayons de modifier le code postal de cette personne
#include <iostream>
#include "Personne.h"
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é ?
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
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
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;
}
C++
En testant maintenant, le code postal a bien été modifié
#include <iostream>
#include "Personne.h"
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;
}
C++
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
C++
Déclarons un pointeur sur Adresse dans Personne.h
Adresse *adresse;
I c
ELH
U
L MO
f E
c hre
c A
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
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;
}
C++
Modifions l’instanciation d’Adresse et la récupération du codePostal
#include <iostream>
#include "Personne.h"
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
C++
Modifions l’instanciation d’Adresse et la récupération du codePostal
#include <iostream>
#include "Personne.h"
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
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
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
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
C++
Comment corriger ça ?
I c
ELH
U
L MO
f E
c hre
c A
C++
Comment corriger ça ?
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
C++
Comment corriger ça ?
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)
{
}
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
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
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
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
};
C++
Exemple
I c
ELH
U
L MO
f E
c hre
c A
C++
Exemple
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
C++
Exemple
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
C++
Exemple
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
C++
Exemple
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
C++
Exemple
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
C++
Contenu de Etudiant.h Contenu de Enseignant.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;
C++
Contenu de Etudiant.h Contenu de Enseignant.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;
Remarque
Contenu de Etudiant.h
#include "Etudiant.h"
Contenu de Etudiant.h
#include "Etudiant.h"
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
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
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
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
C++
Question
I c
ELH
U
L MO
f E
c hre
c A
C++
Question
I c
ELH
Etudiant(int numero, string nom, string prenom, char genre, string
niveau);
U
L MO
f E
c hre
c A
C++
Question
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
}
C++
Question
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
}
C++
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
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
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
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;
}
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
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é
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
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
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
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)
{
}
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
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
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)
C++
Redéfinition (override)
Définir une méthode dans une classe qui est déjà définie dans la classe mère
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
C++
Redéfinition (override)
Définir une méthode dans une classe qui est déjà définie dans la classe mère
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
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
C++
Il faut commencer par la définir dans Etudiant.h
void afficherDetails() const;
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
C++
Il faut commencer par la définir dans Etudiant.h
void afficherDetails() const;
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
*/
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
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
*/
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
*/
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
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);
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
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++
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++
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
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
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
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();
}
C++
C++
Hypothèse et problématique
C++
Hypothèse et problématique
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
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
C++
Dans Etudiant.h et Enseignant.h, déclarer getStatutAcademique()
I c
ELH
U
L MO
f E
c hre
c A
C++
Dans Etudiant.h et Enseignant.h, déclarer getStatutAcademique()
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
C++
Dans Etudiant.h et Enseignant.h, déclarer getStatutAcademique()
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
C++
C++
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
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
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
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
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;
}
C++
#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;
}
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
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
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
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)
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
C++
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;
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
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
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
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
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++;
}
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;
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
C++
Énumération
Ensemble de constante
C++
Énumération
Ensemble de constante
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
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
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
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
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
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
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
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
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
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
}