Date de première publication : 2012/10/12
Polymorphisme : virtual
- Construire une classe
Personne
avec un attribut privé "nom" de typestring
La classe string
appartient à l'espace de nommage std
. Voici les trois manières d'utiliser
le type string
:
std::string
using std::string;
- using namespace std;
- Ajouter une méthode publique
afficher()
qui affiche le nom sur la sortie standard - Ajouter un constructeur public qui prend en paramètre une chaîne et qui initialise le nom
- Instancier et afficher une personne
p1
- Déclarer une classe
Etudiant
qui dérive dePersonne
- Instancier et afficher un étudiant
e
- Corriger sans modifier la classe
Personne
Le compilateur râle d'abord parce qu'il n'y a pas de constructeur par défaut.
Si on fournit un constructeur avec paramètre, il faut bien utiliser la liste d'initialisation pour appeler
le seul constructeur défini dans la classe Personne
.
- Ajouter une méthode publique
info()
dans les deux classes. Dans la classePersonne
, la méthode affiche sur la sortie standard "Personne" et pour la classeEtudiant
, "Etudiant". - Appeler
p1.info()
ete.info()
. Que remarquez-vous ? - Créer un objet
Personne p2 = e;
. Appelerinfo()
, que se passe-t'il ? - Instancier une
Personne * pp1 = new Etudiant("dd");
Appelerinfo()
, que se passe-t'il ? - Ajouter le mot-clé
virtual
sur chacune des méthodesinfo()
? Que remarquez-vous ?
Si vous avez codé proprement, vous avez fait un delete
sur pp1
. Pour que le destructeur d'Etudiant soit bien appelé, malgré
le fait que pp1
est de type Personne *
, il faut que les destructeurs soient virtual
eux-aussi. C'est très facile à vérifier :
- Ajouter les destructeurs aux classes définies avec un simple affichage sur la console.
- Vérifier que
~Etudiant()
n'est pas appelé lors dudelete pp1;
- Ajouter virtual à
~Personne()
et voir que cela marche bien maintenant
Troncature
- Ajouter le code ci-dessous et appelez ces fonctions en passant une instance d'
Etudiant
. Que remarquez-vous ?
void afficher1(Personne p) { p.info(); }
void afficher2(Personne& p) { p.info(); }
void afficher3(Personne* p) { p->info(); }
La perte d'informations liée à l'usage d'afficher1()
s'appelle une troncature de type. On ne l'observe pas
lorsque l'on utilise une référence ou un pointeur.
On aurait pu nommer afficher1()
et afficher3()
avec le même identifiant. Le compilateur aura fait la différence avec
le type du paramètre (surcharge). La différentiation n'est pas possible entre afficher1()
et afficher2()
.