Vous êtes sur la page 1sur 119

Hritage simple (1/3)

Hritage [Delannoy, 2004] :


Un des fondements de la P.O.O A la base des possibilits de rutilisation de composants

logiciels Autorisant la dfinition de nouvelles classes drives partir dune classe existante de base

Super-classe ou classe mre Sous-classe ou classe fille : spcialisation de la superclasse - hritage des proprits de la super-classe Possibilit dhritage multiple en C++
66

Hritage simple (2/3)


class CompteBanque { long ident; float solde; public: CompteBanque(long id, float so = 0); void deposer(float); void retirer(float); float getSolde(); }; class ComptePrelevementAuto : public CompteBanque {

};

float prelev; public: void prelever(); ComptePrelevementAuto(long id, float pr, float so);

67

Hritage simple (3/3)


void transfert(CompteBanque cpt1, ComptePrelevementAuto cpt2) { if (cpt2.getSolde() > 100.00) { cpt2.retirer(100.00); cpt1.deposer(100.00); } } void ComptePrelevementAuto::prelever() { if (solde > 100.00) { // KO: solde est un champ priv de la super-classe } }

68

Hritage simple (3/3)


void transfert(CompteBanque cpt1, ComptePrelevementAuto cpt2) { if (cpt2.getSolde() > 100.00) { cpt2.retirer(100.00); cpt1.deposer(100.00); } } void ComptePrelevementAuto::prelever() { if (solde > 100.00) { // KO: solde est un champ priv de la super-classe } }

Une sous-classe na pas accs aux membres privs de sa super-classe!!

68

Hritage simple (3/3)


void transfert(CompteBanque cpt1, ComptePrelevementAuto cpt2) { if (cpt2.getSolde() > 100.00) { cpt2.retirer(100.00); cpt1.deposer(100.00); } } void void ComptePrelevementAuto::prelever() ComptePrelevementAuto::prelever() { { if > 100.00) if (solde (getSolde() > 100.00) { { // solde est un de la super-classe // KO: La sous-classe a champ accs priv aux mthodes publiques de } // sa super-classe sans avoir prciser quel objet } // elle sapplique } }

Une sous-classe na pas accs aux membres privs de sa super-classe!!

68

Hritage simple et constructeurs (1/4)


class Base { int a; public: Base() : a(0) {} Base(int A) : a(A) {} }; class Derived : public Base { int b; public: Derived() : b(0) {} // appel implicite Base() Derived(int i, int j) : Base(i), b(j) {} // appel explicite };

69

Hritage simple et constructeurs (1/4)


class Base { int a; public: Base() : a(0) {} Base(int A) : a(A) {} };

// Base() { a=0; }

class Derived : public Base { int b; public: Derived() : b(0) {} // appel implicite Base() Derived(int i, int j) : Base(i), b(j) {} // appel explicite };

69

Hritage simple et constructeurs (1/4)


class Base { int a; public: Base() : a(0) {} Base(int A) : a(A) {} };

// Base() { a=0; } // Base(int A) { a=A; }

class Derived : public Base { int b; public: Derived() : b(0) {} // appel implicite Base() Derived(int i, int j) : Base(i), b(j) {} // appel explicite };

69

Hritage simple et constructeurs (1/4)


class Base { int a; public: Base() : a(0) {} Base(int A) : a(A) {} };

// Base() { a=0; } // Base(int A) { a=A; }

class Derived : public Base { int b; public: Derived() : b(0) {} // appel implicite Base() Derived(int i, int j) : Base(i), b(j) {} // appel explicite }; Derived obj; construction dun objet de la classe Base puis dun objet de la classe Derived

Destruction de obj appel automatique au destructeur de la classe Derived puis celui de la classe Base (ordre inverse des constructeurs)

69

Hritage simple et constructeurs (2/4)


// Exemple repris de [Delannoy, 2004] page 254 #include <iostream> using namespace std ; // ************ classe point ********************* class point { int x, y ; public : // constructeur de point ("inline") point (int abs=0, int ord=0) { cout << "++ constr. point : " << abs << " " << ord << endl; x = abs ; y =ord ; } ~point () // destructeur de point ("inline") { cout << "-- destr. point : " << x << " " << y << endl ; } } ;

70

Hritage simple et constructeurs (3/4)


// ************ classe pointcol ****************** class pointcol : public point { short couleur ; public : pointcol (int, int, short) ; // dclaration constructeur pointcol ~pointcol () // destructeur de pointcol ("inline") { cout << "-- dest. pointcol - couleur : " << couleur << endl ; } } ; pointcol::pointcol (int abs=0, int ord=0, short cl=1) : point (abs, ord) { cout << "++ constr. pointcol : " << abs << " " << ord << " " << cl << endl ; couleur = cl ; }

71

Hritage simple et constructeurs (4/4)


// ************ programme d'essai **************** int main() { pointcol a(10,15,3) ; // objets non dynamiques pointcol b (2,3) ; pointcol c (12) ; pointcol * adr ; adr = new pointcol (12,25) ; // objet dynamique delete adr ; }

72

Hritage simple et constructeurs (4/4)


// ************ programme d'essai **************** int main() { pointcol a(10,15,3) ; // objets non dynamiques pointcol b (2,3) ; pointcol c (12) ; pointcol * adr ; adr = new pointcol (12,25) ; // objet dynamique delete adr ; } ++ constr. point : 10 15
++ ++ ++ ++ ++ ++ ++ --------constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : : 10 15 3 2 3 : 2 3 1 12 0 : 12 0 1 12 25 : 12 25 1 couleur : 12 25 couleur : 12 0 couleur : 2 3 couleur : 10 15

Rsultat :

1 1 1 3

72

Hritage simple et constructeurs (4/4)


// ************ programme d'essai **************** int main() { pointcol a(10,15,3) ; // objets non dynamiques pointcol b (2,3) ; pointcol c (12) ; pointcol * adr ; adr = new pointcol (12,25) ; // objet dynamique delete adr ; } ++ constr. point : 10 15
++ ++ ++ ++ ++ ++ ++ --------constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : : 10 15 3 2 3 : 2 3 1 12 0 : 12 0 1 12 25 : 12 25 1 couleur : 12 25 couleur : 12 0 couleur : 2 3 couleur : 10 15

Rsultat :

1 1 1 3

72

Hritage simple et constructeurs (4/4)


// ************ programme d'essai **************** int main() { pointcol a(10,15,3) ; // objets non dynamiques pointcol b (2,3) ; pointcol c (12) ; pointcol * adr ; adr = new pointcol (12,25) ; // objet dynamique delete adr ; } ++ constr. point : 10 15
++ ++ ++ ++ ++ ++ ++ --------constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : : 10 15 3 2 3 : 2 3 1 12 0 : 12 0 1 12 25 : 12 25 1 couleur : 12 25 couleur : 12 0 couleur : 2 3 couleur : 10 15

Rsultat :

1 1 1 3

72

Hritage simple et constructeurs (4/4)


// ************ programme d'essai **************** int main() { pointcol a(10,15,3) ; // objets non dynamiques pointcol b (2,3) ; pointcol c (12) ; pointcol * adr ; adr = new pointcol (12,25) ; // objet dynamique delete adr ; } ++ constr. point : 10 15
++ ++ ++ ++ ++ ++ ++ --------constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : : 10 15 3 2 3 : 2 3 1 12 0 : 12 0 1 12 25 : 12 25 1 couleur : 12 25 couleur : 12 0 couleur : 2 3 couleur : 10 15

Rsultat :

1 1 1 3

72

Hritage simple et constructeurs (4/4)


// ************ programme d'essai **************** int main() { pointcol a(10,15,3) ; // objets non dynamiques pointcol b (2,3) ; pointcol c (12) ; pointcol * adr ; adr = new pointcol (12,25) ; // objet dynamique delete adr ; } ++ constr. point : 10 15
++ ++ ++ ++ ++ ++ ++ --------constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : : 10 15 3 2 3 : 2 3 1 12 0 : 12 0 1 12 25 : 12 25 1 couleur : 12 25 couleur : 12 0 couleur : 2 3 couleur : 10 15

Rsultat :

1 1 1 3

72

Hritage simple et constructeurs (4/4)


// ************ programme d'essai **************** int main() { pointcol a(10,15,3) ; // objets non dynamiques pointcol b (2,3) ; pointcol c (12) ; pointcol * adr ; adr = new pointcol (12,25) ; // objet dynamique delete adr ; } ++ constr. point : 10 15
++ ++ ++ ++ ++ ++ ++ --------constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : : 10 15 3 2 3 : 2 3 1 12 0 : 12 0 1 12 25 : 12 25 1 couleur : 12 25 couleur : 12 0 couleur : 2 3 couleur : 10 15

Rsultat :

1 1 1 3

72

Hritage simple et constructeurs (4/4)


// ************ programme d'essai **************** int main() { pointcol a(10,15,3) ; // objets non dynamiques pointcol b (2,3) ; pointcol c (12) ; pointcol * adr ; adr = new pointcol (12,25) ; // objet dynamique delete adr ; } ++ constr. point : 10 15
++ ++ ++ ++ ++ ++ ++ --------constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : : 10 15 3 2 3 : 2 3 1 12 0 : 12 0 1 12 25 : 12 25 1 couleur : 12 25 couleur : 12 0 couleur : 2 3 couleur : 10 15

Rsultat :

1 1 1 3

72

Hritage simple et constructeurs (4/4)


// ************ programme d'essai **************** int main() { pointcol a(10,15,3) ; // objets non dynamiques pointcol b (2,3) ; pointcol c (12) ; pointcol * adr ; adr = new pointcol (12,25) ; // objet dynamique delete adr ; } ++ constr. point : 10 15
++ ++ ++ ++ ++ ++ ++ --------constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : : 10 15 3 2 3 : 2 3 1 12 0 : 12 0 1 12 25 : 12 25 1 couleur : 12 25 couleur : 12 0 couleur : 2 3 couleur : 10 15

Rsultat :

1 1 1 3

72

Hritage simple et constructeurs (4/4)


// ************ programme d'essai **************** int main() { pointcol a(10,15,3) ; // objets non dynamiques pointcol b (2,3) ; pointcol c (12) ; pointcol * adr ; adr = new pointcol (12,25) ; // objet dynamique delete adr ; } ++ constr. point : 10 15
++ ++ ++ ++ ++ ++ ++ --------constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : : 10 15 3 2 3 : 2 3 1 12 0 : 12 0 1 12 25 : 12 25 1 couleur : 12 25 couleur : 12 0 couleur : 2 3 couleur : 10 15

Rsultat :

1 1 1 3

72

Hritage simple et constructeurs (4/4)


// ************ programme d'essai **************** int main() { pointcol a(10,15,3) ; // objets non dynamiques pointcol b (2,3) ; pointcol c (12) ; pointcol * adr ; adr = new pointcol (12,25) ; // objet dynamique delete adr ; } ++ constr. point : 10 15
++ ++ ++ ++ ++ ++ ++ --------constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : : 10 15 3 2 3 : 2 3 1 12 0 : 12 0 1 12 25 : 12 25 1 couleur : 12 25 couleur : 12 0 couleur : 2 3 couleur : 10 15

Rsultat :

1 1 1 3

72

Hritage simple et constructeurs (4/4)


// ************ programme d'essai **************** int main() { pointcol a(10,15,3) ; // objets non dynamiques pointcol b (2,3) ; pointcol c (12) ; pointcol * adr ; adr = new pointcol (12,25) ; // objet dynamique delete adr ; } ++ constr. point : 10 15
++ ++ ++ ++ ++ ++ ++ --------constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : : 10 15 3 2 3 : 2 3 1 12 0 : 12 0 1 12 25 : 12 25 1 couleur : 12 25 couleur : 12 0 couleur : 2 3 couleur : 10 15

Rsultat :

1 1 1 3

72

Hritage simple et constructeurs (4/4)


// ************ programme d'essai **************** int main() { pointcol a(10,15,3) ; // objets non dynamiques pointcol b (2,3) ; pointcol c (12) ; pointcol * adr ; adr = new pointcol (12,25) ; // objet dynamique delete adr ; } ++ constr. point : 10 15
++ ++ ++ ++ ++ ++ ++ --------constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : : 10 15 3 2 3 : 2 3 1 12 0 : 12 0 1 12 25 : 12 25 1 couleur : 12 25 couleur : 12 0 couleur : 2 3 couleur : 10 15

Rsultat :

1 1 1 3

72

Hritage simple et constructeurs (4/4)


// ************ programme d'essai **************** int main() { pointcol a(10,15,3) ; // objets non dynamiques pointcol b (2,3) ; pointcol c (12) ; pointcol * adr ; adr = new pointcol (12,25) ; // objet dynamique delete adr ; } ++ constr. point : 10 15
++ ++ ++ ++ ++ ++ ++ --------constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol constr. point : constr. pointcol dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : dest. pointcol destr. point : : 10 15 3 2 3 : 2 3 1 12 0 : 12 0 1 12 25 : 12 25 1 couleur : 12 25 couleur : 12 0 couleur : 2 3 couleur : 10 15

Rsultat :

1 1 1 3

72

Hritage simple et constructeurs par copie (1/7)


#include <iostream> using namespace std ; class point { int x, y ; public : point (int abs=0, int { x = abs ; y = ord cout << "++ point } point (point & p) // { x = p.x ; y = p.y cout << "CR point } } ;

ord=0) // constructeur usuel ; " << x << " " << y << endl ; constructeur de recopie ; " << x << " " << y << endl ;

73

Hritage simple et constructeurs par copie (1/7)


#include <iostream> using namespace std ; class point { int x, y ; public : point (int abs=0, int { x = abs ; y = ord cout << "++ point } point (point & p) // { x = p.x ; y = p.y cout << "CR point } } ;

ord=0) // constructeur usuel ; " << x << " " << y << endl ; constructeur de recopie ; " << x << " " << y << endl ;

Rappel : appel du constructeur par copie lors de linitialisation dun objet par un objet de mme type de la transmission de la valeur dun objet en argument ou en retour de fonction

73

Hritage simple et constructeurs par copie (2/7)


class pointcol : public point { int coul ; public : // constructeur usuel pointcol (int abs=0, int ord=0, int cl=1) : point (abs, ord) { coul = cl ; cout << "++ pointcol " << coul << endl ; } // constructeur de recopie // il y aura conversion implicite de p dans le type point pointcol (pointcol & p) : point (p) { coul = p.coul ; cout << "CR pointcol " << coul << endl ; } } ;

74

Hritage simple et constructeurs par copie (2/7)


class pointcol : public point { int coul ; public : // constructeur usuel pointcol (int abs=0, int ord=0, int cl=1) : point (abs, ord) { coul = cl ; cout << "++ pointcol " << coul << endl ; } // constructeur de recopie // il y aura conversion implicite de p dans le type point pointcol (pointcol & p) : point (p) { coul = p.coul ; cout << "CR pointcol " << coul << endl ; } } ;

Si pas de constructeur par copie dfini dans la sous-classe Appel du constructeur par copie par dfaut de la sous-classe et donc du constructeur par copie de la super-classe

74

Hritage simple et constructeurs par copie (3/7)


void fct (pointcol pc) { cout << "*** entree dans fct ***" } << endl ;

int main() { void fct (pointcol) ; // Dclaration de f pointcol a (2,3,4) ; fct (a) ; // appel de fct avec a transmis par valeur }

75

Hritage simple et constructeurs par copie (3/7)


void fct (pointcol pc) { cout << "*** entree dans fct ***" } << endl ;

int main() { void fct (pointcol) ; // Dclaration de f pointcol a (2,3,4) ; fct (a) ; // appel de fct avec a transmis par valeur }

Rsultat :
++ point 2 3 ++ pointcol 4 CR point 2 3 CR pointcol 4 *** entree dans fct *** 75

Hritage simple et constructeurs par copie (3/7)


void fct (pointcol pc) { cout << "*** entree dans fct ***" } << endl ;

int main() { void fct (pointcol) ; // Dclaration de f pointcol a (2,3,4) ; fct (a) ; // appel de fct avec a transmis par valeur }

Rsultat :
++ point 2 3 pointcol a (2,3,4) ; ++ pointcol 4 CR point 2 3 CR pointcol 4 *** entree dans fct *** 75

Hritage simple et constructeurs par copie (3/7)


void fct (pointcol pc) { cout << "*** entree dans fct ***" } << endl ;

int main() { void fct (pointcol) ; // Dclaration de f pointcol a (2,3,4) ; fct (a) ; // appel de fct avec a transmis par valeur }

Rsultat :
++ point 2 3 pointcol a (2,3,4) ; ++ pointcol 4 CR point 2 3 fct (a) ; CR pointcol 4 *** entree dans fct *** 75

Hritage simple et constructeurs par copie (4/7)


Soit une classe B, drivant dune classe A : B b0; B b1 (b0); // Appel du constructeur par copie de B B b2 = b1 ; // Appel du constructeur par copie de B Si aucun constructeur par copie dfini dans B : Appel du constructeur par copie par dfaut faisant une copie membre membre Traitement de la partie de b1 hrite de la classe A comme dun membre du type A Appel du constructeur par copie de A Si un constructeur par copie dfini dans B :

B ( [const] B&)

Appel du constructeur de A sans argument ou dont tous les arguments

possde une valeur par dfaut


B ( [const] B& x) : A (x)

Appel du constructeur par copie de A

76

Hritage simple et constructeurs par copie (4/7)


Soit une classe B, drivant dune classe A : B b0; B b1 (b0); // Appel du constructeur par copie de B B b2 = b1 ; // Appel du constructeur par copie de B Si aucun constructeur par copie dfini dans B : Appel du constructeur par copie par dfaut faisant une copie membre membre Traitement de la partie de b1 hrite de la classe A comme dun membre du type A Appel du constructeur par copie de A Si un constructeur par copie dfini dans B :

B ( [const] B&)

Appel du constructeur de A sans argument ou dont tous les arguments

possde une valeur par dfaut


B ( [const] B& x) : A (x)

Appel du constructeur par copie de A

Le constructeur par copie de la classe drive doit prendre en charge lintgralit de la recopie de lobjet et galement de sa partie hrite

76

Hritage simple et constructeurs par copie (5/7)


#include <iostream> using namespace std; // Exemple repris et adapt de "C++ - Testez-vous" // de A. Zerdouk, Ellipses, 2001 class Classe1 { public : Classe1(){ cout << "Classe1::Classe1()" << endl;} Classe1(const Classe1 & obj) { cout << "Classe1::Classe1(const Classe1&)" << endl;} }; class Classe2 : public Classe1 { public: Classe2() { cout << "Classe2::Classe2()" << endl;} Classe2(const Classe2 & obj) { cout << "Classe2::Classe2(const Classe2&)" << endl;} };

77

Hritage simple et constructeurs par copie (6/7)


int main() { Classe2 obj1; Classe2 obj2(obj1); // Classe2 obj2=obj1; }

Rsultat :
Classe1::Classe1() Classe2::Classe2() Classe1::Classe1() Classe2::Classe2(const Classe2&)

78

Hritage simple et constructeurs par copie (6/7)


int main() { Classe2 obj1; Classe2 obj2(obj1); // Classe2 obj2=obj1; }

Rsultat :
Classe1::Classe1() Classe2::Classe2() Classe1::Classe1() Classe2::Classe2(const Classe2&)

78

Hritage simple et constructeurs par copie (6/7)


int main() { Classe2 obj1; Classe2 obj2(obj1); // Classe2 obj2=obj1; }

Rsultat :
Classe1::Classe1() Classe2::Classe2() Classe1::Classe1() Classe2::Classe2(const Classe2&)

78

Hritage simple et constructeurs par copie (6/7)


int main() { Classe2 obj1; Classe2 obj2(obj1); // Classe2 obj2=obj1; }

Rsultat :
Classe1::Classe1() Classe2::Classe2() Classe1::Classe1() Classe2::Classe2(const Classe2&)

78

Hritage simple et constructeurs par copie (6/7)


int main() { Classe2 obj1; Classe2 obj2(obj1); // Classe2 obj2=obj1; }

Rsultat :
Classe1::Classe1() Classe2::Classe2() Classe1::Classe1() Classe2::Classe2(const Classe2&)

78

Hritage simple et constructeurs par copie (6/7)


int main() { Classe2 obj1; Classe2 obj2(obj1); // Classe2 obj2=obj1; }

Rsultat :
Classe1::Classe1() Classe2::Classe2() Classe1::Classe1() Classe2::Classe2(const Classe2&)

Appel du constructeur de la classe mre car pas dappel explicite au copy const. de la classe mre dans le copy const. de la classe fille

78

Hritage simple et constructeurs par copie (7/7)


Si le constructeur par recopie de la Classe2 dfini comme suit :
// Appel explicite au copy const. de la classe mre Classe2(const Classe2 & obj) : Classe1(obj) { cout << "Classe2::Classe2(const Classe2&)" << endl;} int main() { Classe2 obj1; Classe2 obj2(obj1); // Classe2 obj2=obj1; }

Rsultat :
Classe1::Classe1() Classe2::Classe2() Classe1::Classe1(const Classe1&) Classe2::Classe2(const Classe2&) 79

Hritage simple et constructeurs par copie (7/7)


Si le constructeur par recopie de la Classe2 dfini comme suit :
// Appel explicite au copy const. de la classe mre Classe2(const Classe2 & obj) : Classe1(obj) { cout << "Classe2::Classe2(const Classe2&)" << endl;} int main() { Classe2 obj1; Classe2 obj2(obj1); // Classe2 obj2=obj1; }

Rsultat :
Classe1::Classe1() Classe2::Classe2() Classe1::Classe1(const Classe1&) Classe2::Classe2(const Classe2&) 79

Hritage simple et constructeurs par copie (7/7)


Si le constructeur par recopie de la Classe2 dfini comme suit :
// Appel explicite au copy const. de la classe mre Classe2(const Classe2 & obj) : Classe1(obj) { cout << "Classe2::Classe2(const Classe2&)" << endl;} int main() { Classe2 obj1; Classe2 obj2(obj1); // Classe2 obj2=obj1; }

Rsultat :
Classe1::Classe1() Classe2::Classe2() Classe1::Classe1(const Classe1&) Classe2::Classe2(const Classe2&) 79

Hritage simple et constructeurs par copie (7/7)


Si le constructeur par recopie de la Classe2 dfini comme suit :
// Appel explicite au copy const. de la classe mre Classe2(const Classe2 & obj) : Classe1(obj) { cout << "Classe2::Classe2(const Classe2&)" << endl;} int main() { Classe2 obj1; Classe2 obj2(obj1); // Classe2 obj2=obj1; }

Rsultat :
Classe1::Classe1() Classe2::Classe2() Classe1::Classe1(const Classe1&) Classe2::Classe2(const Classe2&) 79

Hritage simple et constructeurs par copie (7/7)


Si le constructeur par recopie de la Classe2 dfini comme suit :
// Appel explicite au copy const. de la classe mre Classe2(const Classe2 & obj) : Classe1(obj) { cout << "Classe2::Classe2(const Classe2&)" << endl;} int main() { Classe2 obj1; Classe2 obj2(obj1); // Classe2 obj2=obj1; }

Rsultat :
Classe1::Classe1() Classe2::Classe2() Classe1::Classe1(const Classe1&) Classe2::Classe2(const Classe2&) 79

Hritage simple et constructeurs par copie (7/7)


Si le constructeur par recopie de la Classe2 dfini comme suit :
// Appel explicite au copy const. de la classe mre Classe2(const Classe2 & obj) : Classe1(obj) { cout << "Classe2::Classe2(const Classe2&)" << endl;} int main() { Classe2 obj1; Classe2 obj2(obj1); // Classe2 obj2=obj1; }

Rsultat :
Classe1::Classe1() Classe2::Classe2() Classe1::Classe1(const Classe1&) Classe2::Classe2(const Classe2&) 79

Contrle des accs (1/9)


Trois qualificatifs pour les membres dune classe : public, private et protected
Public : membre accessible non seulement aux fonctions membres (mthodes) ou aux fonctions amies mais galement aux clients de la classe Private : membre accessible uniquement aux fonctions membres (publiques ou prives) et aux fonctions amies de la classe Protected : comme private mais membre accessible par une classe drive 80

Contrle des accs (2/9)


class Point { protected: // attributs protgs int _x; int _y; public: Point (...); affiche(); ... }; class Pointcol : public Point { short _couleur; public: void affiche() { // Possibilit daccder aux attributs protgs // _x et _y de la super-classe dans la sous-classe cout << "je suis en " << _x << " " << _y << endl; cout << " et ma couleur est " << _couleur << endl; } };

81

Contrle des accs (3/9)


Membre protg dune classe :

quivalent un membre priv pour les utilisateurs de la classe Comparable un membre public concepteur dune classe drive pour le

Mais comparable un membre priv pour les utilisateurs de la classe drive Possibilit de violer lencapsulation des donnes
82

Contrle des accs (3/9)


Membre protg dune classe :

quivalent un membre priv pour les utilisateurs de la classe Comparable un membre public concepteur dune classe drive pour le

Mais comparable un membre priv pour les utilisateurs de la classe drive

Possibilit de violer lencapsulation des donnes


82

Contrle des accs (4/9)


Plusieurs modes de drivation de classe : Possibilit dutiliser public, protected ou private pour spcifier le mode de drivation dune classe Dtermination, par le mode de drivation, des membres de la super-classe accessibles dans la sous-classe Drivation prive par dfaut

83

Contrle des accs (5/9)


Drivation publique :
Conservation du statut des membres publics et protgs de la classe de base dans la classe drive Forme la plus courante dhritage modlisant : une classe drive est une spcialisation de la classe de base
class Base { public: void mthodePublique1(); protected: void mthodeProtge(); private: void MthodePrive(); }; class Derivee : public Base { public: int MthodePublic2() { mthodePublique1(); // OK mthodeProtge(); // OK MthodePrive(); // KO } };

84

Contrle des accs (6/9)


Drivation publique :
statut dans la classe de base
public protected private

nouveau statut accs aux fonctions accs un membres et amies de la utilisateur de la dans la classe drive classe drive classe drive
oui oui non oui non non public protected private

85

Contrle des accs (6/9)


Drivation publique :
statut dans la classe de base
public protected private

nouveau statut accs aux fonctions accs un membres et amies de la utilisateur de la dans la classe drive classe drive classe drive
oui oui non oui non non public protected private

Les fonctions ou classes amies de la classe de base ont accs tous les membres de la classe de base quils soient dfinis comme public, private ou protected 85

Contrle des accs (7/9)


Drivation prive :
Transformation du statut des membres publics et protgs de la classe de base en statut priv dans la classe drive Pour ne pas accder aux anciens membres de la classe de base lorsquils ont t redfinis dans la classe drive Pour adapter linterface dune classe, la classe drive napportant rien de plus que la classe de base (pas de nouvelles proprits) mais offrant une utilisation diffrente des membres
class Base class Derivee : private Base { { public: void mthodePrive() void mthodePublique(); { ... }; mthodePublique(); // OK } };

86

Contrle des accs (7/9)


Drivation prive :
Transformation du statut des membres publics et protgs de la classe de base en statut priv dans la classe drive Pour ne pas accder aux anciens membres de la classe de base lorsquils ont t redfinis dans la classe drive Pour adapter linterface dune classe, la classe drive napportant rien de plus que la classe de base (pas de nouvelles proprits) mais offrant une utilisation diffrente des membres
class Base class Derivee : private Base { { public: void mthodePrive() void mthodePublique(); { ... }; mthodePublique(); // OK } }; Derivee obj; obj.mthodePublique(); // KO

86

Contrle des accs (7/9)


Drivation prive :
Transformation du statut des membres publics et protgs de la classe de base en statut priv dans la classe drive Pour ne pas accder aux anciens membres de la classe de base lorsquils ont t redfinis dans la classe drive Pour adapter linterface dune classe, la classe drive napportant rien de plus que la classe de base (pas de nouvelles proprits) mais offrant une utilisation diffrente des membres
class Base class Derivee : private Base { { public: void mthodePrive() void mthodePublique(); { ... }; mthodePublique(); // OK } }; Derivee obj; obj.mthodePublique(); // KO Base* b= &obj; // KO

86

Contrle des accs (8/9)


Drivation prive (suite) Possibilit de laisser un membre de la classe de base public dans la classe drive
Redclaration explicite dans la classe drive Utilisation de using
class Derivee : private Base // drivation prive { public: Base::mthodePublique1(); // La mthode publique // de la classe de base // devient publique dans // la classe drive using Base::mthodePublique2(); //idem };

87

Contrle des accs (9/9)


Drivation protge : Transformation du statut des membres publics et protgs de la classe de base en statut protg dans la classe drive

88

Contrle des accs (9/9)


Drivation protge : Transformation du statut des membres publics et protgs de la classe de base en statut protg dans la classe drive
classe statut initial public protg priv de accs fonct. membres /amies oui oui oui base drive publique drive accs nouveau accs nouveau utilis. statut utilis. statut oui non non public oui protg non priv non protg protg priv protge accs utilis. non non non drive nouveau statut priv priv priv prive accs utilis. non non non

88

Contrle des accs (9/9)


Drivation protge : Transformation du statut des membres publics et protgs de la classe de base en statut protg dans la classe drive
classe statut initial public protg priv de accs fonct. membres /amies oui oui oui base drive publique drive accs nouveau accs nouveau utilis. statut utilis. statut oui non non public oui protg non priv non protg protg priv protge accs utilis. non non non drive nouveau statut priv priv priv prive accs utilis. non non non

Ne pas confondre le mode de drivation et le statut des membres dune classe 88

Hritage simple constructeurs/destructeurs/constructeurs par copie


Pas dhritage des constructeurs et destructeurs il faut les redfinir Appel implicite des constructeurs par dfaut des classes de base (super-classe) avant le constructeur de la classe drive (sous-classe) Possibilit de passage de paramtres aux constructeurs de la classe de base dans le constructeur de la classe drive par appel explicite Appel automatique des destructeurs dans l'ordre inverse des constructeurs Pas dhritage des constructeurs de copie et des oprateurs d'affectation
89

Hritage simple et redfinition/sur-dfinition (1/2)


class Base { protected : int a; char b; public : void affiche(); };

class Derivee : public Base { float a; // redfinition de lattribut a public : void affiche(); // redfinition de la mthode affiche float GetADelaClasseDerivee(){return a;} ; int GetADeLaClasseDeBase() {return Base::a;} };

90

Hritage simple et redfinition/sur-dfinition (1/2)


class Base { protected : int a; char b; public : void affiche(); }; void Base::affiche() { cout << a << b << endl; }

class Derivee : public Base { float a; // redfinition de lattribut a public : void affiche(); // redfinition de la mthode affiche float GetADelaClasseDerivee(){return a;} ; int GetADeLaClasseDeBase() {return Base::a;} };

90

Hritage simple et redfinition/sur-dfinition (1/2)


class Base { protected : int a; char b; public : void affiche(); }; void Base::affiche() { cout << a << b << endl; } void Derivee::affiche() { cout << "a est un rel"; }

class Derivee : public Base { float a; // redfinition de lattribut a public : void affiche(); // redfinition de la mthode affiche float GetADelaClasseDerivee(){return a;} ; int GetADeLaClasseDeBase() {return Base::a;} };

90

Hritage simple et redfinition/sur-dfinition (1/2)


class Base { protected : int a; char b; public : void affiche(); }; void Base::affiche() { cout << a << b << endl; } void Derivee::affiche() { //attention appel rcursif affiche(); cout << "a est un rel"; }

class Derivee : public Base { float a; // redfinition de lattribut a public : void affiche(); // redfinition de la mthode affiche float GetADelaClasseDerivee(){return a;} ; int GetADeLaClasseDeBase() {return Base::a;} };

90

Hritage simple et redfinition/sur-dfinition (1/2)


class Base { protected : int a; char b; public : void affiche(); }; void Base::affiche() { cout << a << b << endl; } void Derivee::affiche() { // appel de affiche //attention appel rcursif // de la super-classe affiche(); Base::affiche(); cout << "a est un rel"; }

class Derivee : public Base { float a; // redfinition de lattribut a public : void affiche(); // redfinition de la mthode affiche float GetADelaClasseDerivee(){return a;} ; int GetADeLaClasseDeBase() {return Base::a;} };

90

Hritage simple et redfinition/sur-dfinition (2/2)


class A { public : void f (int); void f (char); void g (int); void g (char); }; class B : public A { public : void f (int); void f (float); }; int main() { int n; float x; char c; B b; b.f(n); b.f(x); b.f(c); b.g(n); b.g(x); b.g(c); }

91

Hritage simple et redfinition/sur-dfinition (2/2)


class A { public : void f (int); void f (char); void g (int); void g (char); }; class B : public A { public : void f (int); void f (float); }; int main() { int n; float x; char c; B b; b.f(n); // appel de B::f(int) b.f(x); b.f(c); b.g(n); b.g(x); b.g(c); }

91

Hritage simple et redfinition/sur-dfinition (2/2)


class A { public : void f (int); void f (char); void g (int); void g (char); }; class B : public A { public : void f (int); void f (float); }; int main() { int n; float x; char c; B b; b.f(n); // appel de B::f(int) b.f(x); // appel de B::f(float) b.f(c); b.g(n); b.g(x); b.g(c); }

91

Hritage simple et redfinition/sur-dfinition (2/2)


class A { public : void f (int); void f (char); void g (int); void g (char); }; class B : public A { public : void f (int); void f (float); }; int main() { int n; float x; char c; B b; b.f(n); // appel de B::f(int) b.f(x); // appel de B::f(float) b.f(c); // appel de B::f(int) b.g(n); b.g(x); b.g(c); }

91

Hritage simple et redfinition/sur-dfinition (2/2)


class A { public : void f (int); void f (char); void g (int); void g (char); }; class B : public A { public : void f (int); void f (float); }; int main() { int n; float x; char c; B b; b.f(n); // appel de B::f(int) b.f(x); // appel de B::f(float) b.f(c); // appel de B::f(int) // avec conversion de c en int // pas dappel A::f(int) // ni dappel A::f(char) b.g(n); b.g(x); b.g(c); }

91

Hritage simple et redfinition/sur-dfinition (2/2)


class A { public : void f (int); void f (char); void g (int); void g (char); }; class B : public A { public : void f (int); void f (float); }; int main() { int n; float x; char c; B b; b.f(n); // appel de B::f(int) b.f(x); // appel de B::f(float) b.f(c); // appel de B::f(int) // avec conversion de c en int // pas dappel A::f(int) // ni dappel A::f(char) b.g(n); // appel de A::g(int) b.g(x); b.g(c); }

91

Hritage simple et redfinition/sur-dfinition (2/2)


class A { public : void f (int); void f (char); void g (int); void g (char); }; class B : public A { public : void f (int); void f (float); }; int main() { int n; float x; char c; B b; b.f(n); // appel de B::f(int) b.f(x); // appel de B::f(float) b.f(c); // appel de B::f(int) // avec conversion de c en int // pas dappel A::f(int) // ni dappel A::f(char) b.g(n); // appel de A::g(int) b.g(x); // appel de A::g(int) b.g(c); }

91

Hritage simple et redfinition/sur-dfinition (2/2)


class A { public : void f (int); void f (char); void g (int); void g (char); }; class B : public A { public : void f (int); void f (float); }; int main() { int n; float x; char c; B b; b.f(n); // appel de B::f(int) b.f(x); // appel de B::f(float) b.f(c); // appel de B::f(int) // avec conversion de c en int // pas dappel A::f(int) // ni dappel A::f(char) b.g(n); // appel de A::g(int) b.g(x); // appel de A::g(int) b.g(c); }
// conversion de x en int

91

Hritage simple et redfinition/sur-dfinition (2/2)


class A { public : void f (int); void f (char); void g (int); void g (char); }; class B : public A { public : void f (int); void f (float); }; int main() { int n; float x; char c; B b; b.f(n); // appel de B::f(int) b.f(x); // appel de B::f(float) b.f(c); // appel de B::f(int) // avec conversion de c en int // pas dappel A::f(int) // ni dappel A::f(char) b.g(n); // appel de A::g(int) b.g(x); // appel de A::g(int)
// conversion de x en int b.g(c); // appel de A::g(char)

91

Hritage simple et amiti (1/2)


Mmes autorisations daccs pour les fonctions amies dune classe drive que pour ses mthodes Pas dhritage au niveau des dclarations damiti
class A { friend class ClasseAmie; public: A(int n=0) : attributDeA(n) {} private: int attributDeA; }; class ClasseAmie { public: ClasseAmie(int n=0) : objetMembre(n) {} void affiche1() {cout << objetMembre.attributDeA << endl;} // OK: Cette classe est est amie de A private: A objetMembre; };

92

Hritage simple et amiti (1/2)

Mmes autorisations daccs pour les fonctions amies dune classe drive que pour ses mthodes Pas dhritage au niveau des dclarations damiti

class A { friend class ClasseAmie; public: A(int n=0) : attributDeA(n) {} private: int attributDeA; }; class ClasseAmie { public: ClasseAmie(int n=0) : objetMembre(n) {} void affiche1() {cout << objetMembre.attributDeA << endl;} // OK: Cette classe est est amie de A private: A objetMembre; };

92

Hritage simple et amiti (2/2)


class A { friend class ClasseAmie; public: A(int n=0): attributDeA(n) {} private: int attributDeA; }; class ClasseAmie { public: ClasseAmie(int n=0): objetMembre(n) {} void affiche1() {cout << objetMembre. attributDeA << endl;} // OK: Cette classe est est amie de A private: A objetMembre;

};

93

Hritage simple et amiti (2/2)


class A { friend class ClasseAmie; public: A(int n=0): attributDeA(n) {} private: int attributDeA; }; class ClasseAmie { public: ClasseAmie(int n=0): objetMembre(n) {} void affiche1() {cout << objetMembre. attributDeA << endl;} // OK: Cette classe est est amie de A private: A objetMembre;

}; class ClasseDrive: public ClasseAmie { public: ClasseDrive(int x=0,int y=0): ClasseAmie(x), objetMembre2(y) {} void Ecrit() { cout << objetMembre2.attributDeA << endl; } // ERREUR: ClasseDrive n'est pas amie de A // error: `int A::attributDeA' is private private: A objetMembre2; };

93

Compatibilit entre classe de base et classe drive (1/2)


Possibilit de convertir implicitement une instance dune classe drive en une instance de la classe de base, si lhritage est public Linverse nest pas possible : impossibilit de convertir une instance de la classe de base en instance de la classe drive
ClasseDeBase a; ClasseDrive b; a=b; // // b=a; // // lgal et appel de loprateur = de la classe de Base sil a t redfini ou de loprateur par dfaut sinon illgal error: no match for 'operator=' in b = a'

94

Compatibilit entre classe de base et classe drive (1/2)


Possibilit de convertir implicitement une instance dune classe drive en une instance de la classe de base, si lhritage est public

Linverse nest pas possible : impossibilit de convertir une instance de la classe de base en instance de la classe drive

ClasseDeBase a; ClasseDrive b; a=b; // // b=a; // // lgal et appel de loprateur = de la classe de Base sil a t redfini ou de loprateur par dfaut sinon illgal error: no match for 'operator=' in b = a'

94

Compatibilit entre classe de base et classe drive (2/2)


Possibilit de convertir un pointeur sur une instance de la classe drive en un pointeur sur une instance de la classe de base, si lhritage est public
ClasseDeBase o1, * p1=NULL; ClasseDrive o2, * p2=NULL; p1=&o1; p2=&o2; p1->affiche() ; // Appel de ClasseDeBase::affiche(); p2->affiche() ; // Appel de ClasseDrive::affiche(); p1=p2; // legale: ClasseDrive* vers ClasseDeBase* p1->affiche() ; // Appel de ClasseDeBase::affiche(); // et non de ClasseDrive::affiche(); p2=p1; // erreur sauf si on fait un cast explicite
// error: invalid conversion from `ClasseDeBase*' to `ClasseDriv*'

p2= (ClasseDrive*) p1;

// Possible mais Attention les attributs membres // de la classe drive nauront pas de valeur

95

Hritage simple et oprateur daffectation (1/6)


Si pas de redfinition de loprateur = dans la classe drive : Affectation membre membre Appel implicite loprateur = sur-dfini ou par dfaut de la classe de base pour laffectation de la partie hrite Si redfinition de loprateur = dans la classe drive :
Prise en charge totale de laffectation par loprateur

= de la classe drive

96

Hritage simple et oprateur daffectation (2/6)


#include <iostream> using namespace std ; class point { protected : int x, y ; public : point (int abs=0, int ord=0) { x=abs ; y=ord ;} point & operator = (const point & a) { x = a.x ; y = a.y ; cout << "operateur = de point" << endl; return * this ; } } ;

97

Hritage simple et oprateur daffectation (3/6)


class pointcol : public point { int couleur ; public : pointcol (int abs=0, int ord=0, int c=0); // Pas de redfinition de loprateur = dans la classe drive }; pointcol::pointcol(int abs, int ord, int c) : point(abs,ord) { couleur=c;} int main() { pointcol c, d; d=c; }

98

Hritage simple et oprateur daffectation (3/6)


class pointcol : public point { int couleur ; public : pointcol (int abs=0, int ord=0, int c=0); // Pas de redfinition de loprateur = dans la classe drive }; pointcol::pointcol(int abs, int ord, int c) : point(abs,ord) { couleur=c;} int main() { pointcol c, d; d=c; } operateur = de point

98

Hritage simple et oprateur daffectation (4/6)


class pointcol : public point { int couleur ; public : pointcol (int abs=0, int ord=0, int c=0); // Redfinition de loprateur = dans la classe drive pointcol & operator = (const pointcol & a) { couleur=a.couleur; cout << "operateur = de pointcol" << endl; return * this ; } }; pointcol::pointcol(int abs, int ord, int c) : point(abs,ord) { couleur=c;} int main() { pointcol c, d; d=c; }

99

Hritage simple et oprateur daffectation (4/6)


class pointcol : public point { int couleur ; public : pointcol (int abs=0, int ord=0, int c=0); // Redfinition de loprateur = dans la classe drive pointcol & operator = (const pointcol & a) { couleur=a.couleur; cout << "operateur = de pointcol" << endl; return * this ; } }; pointcol::pointcol(int abs, int ord, int c) : point(abs,ord) { couleur=c;} int main() { pointcol c, d; d=c; }

operateur = de pointcol

99

Hritage simple et oprateur daffectation (5/6)


// Redfinition de loprateur = dans la classe drive // Avec appel explicite loprateur = de la classe de base // en utilisant des conversions de pointeurs pointcol & pointcol::operator = (const pointcol & a) { point * p1; p1=this; // conversion dun pointeur sur pointcol // en pointeur sur point const point *p2= &a; // idem *p1=*p2; // affectation de la partie point de a couleur=a.couleur; cout << "operateur = de pointcol" << endl; return * this ; } int main() { pointcol c, d; d=c; }

100

Hritage simple et oprateur daffectation (5/6)


// Redfinition de loprateur = dans la classe drive // Avec appel explicite loprateur = de la classe de base // en utilisant des conversions de pointeurs pointcol & pointcol::operator = (const pointcol & a) { point * p1; p1=this; // conversion dun pointeur sur pointcol // en pointeur sur point const point *p2= &a; // idem *p1=*p2; // affectation de la partie point de a couleur=a.couleur; cout << "operateur = de pointcol" << endl; return * this ; } int main() { pointcol c, d; d=c; } operateur = de point operateur = de pointcol

100

Hritage simple et oprateur daffectation (6/6)


// Redfinition de loprateur = dans la classe drive // Avec appel explicite loprateur = // de la classe de base pointcol & pointcol::operator = (const pointcol & a) { // Appel explicite loprateur = de point this->point::operator=(a); couleur=a.couleur; cout << "operateur = de pointcol" << endl; return * this ; } int main() { pointcol c, d; d=c; }

101

Hritage simple et oprateur daffectation (6/6)


// Redfinition de loprateur = dans la classe drive // Avec appel explicite loprateur = // de la classe de base pointcol & pointcol::operator = (const pointcol & a) { // Appel explicite loprateur = de point this->point::operator=(a); couleur=a.couleur; cout << "operateur = de pointcol" << endl; return * this ; } int main() { pointcol c, d; d=c; } operateur = de point operateur = de pointcol

101

Hritage multiple (1/5)


Possibilit de crer des classes drives partir de plusieurs classes de base Pour chaque classe de base : possibilit de dfinir le mode d'hritage Appel des constructeurs dans l'ordre de dclaration de l'hritage Appel des destructeurs dans l'ordre inverse de celui des constructeurs

103

Hritage multiple (2/5)


class Point { int x; int y; public: Point(...){...} ~Point(){...} void affiche(){...} }; class Couleur { int coul; public: Couleur(...){...} ~Couleur(){...} void affiche(){...} };

104

Hritage multiple (2/5)


class Point { int x; int y; public: Point(...){...} ~Point(){...} void affiche(){...} }; class Couleur { int coul; public: Couleur(...){...} ~Couleur(){...} void affiche(){...} };

// classe drive de deux autres classes class PointCouleur : public Point, public Couleur { ...

};

104

Hritage multiple (2/5)


class Point { int x; int y; public: Point(...){...} ~Point(){...} void affiche(){...} }; class Couleur { int coul; public: Couleur(...){...} ~Couleur(){...} void affiche(){...} };

// classe drive de deux autres classes class PointCouleur : public Point, public Couleur { ... // Constructeur PointCouleur (...) : Point(...), Couleur(...) };

104

Hritage multiple (2/5)


class Point { int x; int y; public: Point(...){...} ~Point(){...} void affiche(){...} }; class Couleur { int coul; public: Couleur(...){...} ~Couleur(){...} void affiche(){...} };

// classe drive de deux autres classes class PointCouleur : public Point, public Couleur { ... // Constructeur PointCouleur (...) : Point(...), Couleur(...) void affiche(){Point::affiche(); Couleur::affiche(); }

};

104

Hritage multiple (3/5)


int main() { PointCouleur p(1,2,3); cout << endl; p.affiche(); // Appel de affiche() de PointCouleur cout << endl; // Appel "forc" de affiche() de Point p.Point::affiche(); cout << endl; // Appel "forc" de affiche() de Couleur p.Couleur::affiche(); }

105

Hritage multiple (3/5)


int main() { PointCouleur p(1,2,3); cout << endl; p.affiche(); // Appel de affiche() de PointCouleur cout << endl; // Appel "forc" de affiche() de Point p.Point::affiche(); cout << endl; // Appel "forc" de affiche() de Couleur p.Couleur::affiche(); }
** Point::Point(int,int) ** Couleur::Couleur(int) ** PointCouleur::PointCouleur(int,int ,int) Coordonnes : 1 2 Couleur : 3 Coordonnes : 1 2 Couleur : 3 ** PointCouleur::~PointCouleur() ** Couleur::~Couleur() ** Point::~Point()

105

Hritage multiple (3/5)


int main() { PointCouleur p(1,2,3); cout << endl; p.affiche(); // Appel de affiche() de PointCouleur cout << endl; // Appel "forc" de affiche() de Point p.Point::affiche(); cout << endl; // Appel "forc" de affiche() de Couleur p.Couleur::affiche(); }
** Point::Point(int,int) ** Couleur::Couleur(int) ** PointCouleur::PointCouleur(int,int ,int) Coordonnes : 1 2 Couleur : 3 Coordonnes : 1 2 Couleur : 3 ** PointCouleur::~PointCouleur() ** Couleur::~Couleur() ** Point::~Point()

Si affiche() na pas t redfinie dans PointCouleur : error: request for member `affiche' is ambiguous error: candidates are: void Couleur::affiche() void Point::affiche()

105

Fonction/Mthode virtuelle et typage dynamique (1/9)


Liaison statique : type de lobjet point dtermin au moment de la compilation. De mme pour les mthodes invoquer sur cet objet Appel des mthodes correspondant au type du pointeur et non pas au type effectif de lobjet point Polymorphisme possibilit de choisir dynamiquement ( lexcution) une mthode en fonction de la classe effective de lobjet sur lequel elle sapplique liaison dynamique Liaison dynamique obtenue en dfinissant des mthodes virtuelles 114

Fonction/Mthode virtuelle et typage dynamique (2/9)


class Personne { string nom; string prenom; int age; char sexe; public : // Constructeur Personne(string n, string p, int a, char s) { nom=n; prenom=p; age=a; sexe=s; cout << "Personne::Personne("<<nom<< "," << prenom << "," << age << "," << sexe << ")" } // Affichage void Affiche() { if (sexe == 'M') cout << "Monsieur " else cout << "Madame/Mademoiselle " ; cout << prenom << " " << nom << " age de " << age << " ans." << endl; } // Destructeur ~Personne() {cout << "Personne::~Personne()" << endl;} };

<< endl;

115

Fonction/Mthode virtuelle et typage dynamique (3/9)


class Etudiant : public Personne { int note; public: // Constructeur Etudiant(string nm, string p, int a, char s, int n):Personne(nm,p,a,s) { note = n; cout << "Etudiant::Etudiant(" <<GetNom()<< "," << GetPrenom() << ","<< GetAge() << "," << GetSexe() << "," << note << ")" << endl; } void Affiche() // Affichage { Personne::Affiche(); cout << "Il s'agit d'un tudiant ayant pour note :" << note << "." << endl; } // Destructeur ~Etudiant() {cout << "Etudiant::~Etudiant()" << endl;} };

116

Fonction/Mthode virtuelle et typage dynamique (3/9)


class Etudiant : public Personne { int note; public: // Constructeur Etudiant(string nm, string p, int a, char s, int n):Personne(nm,p,a,s) { note = n; cout << "Etudiant::Etudiant(" <<GetNom()<< "," << GetPrenom() << ","<< GetAge() << "," << GetSexe() << "," << note << ")" << endl; } void Affiche() // Affichage { Personne::Affiche(); cout << "Il s'agit d'un tudiant ayant pour note :" << note << "." << endl; } // Destructeur ~Etudiant() {cout << "Etudiant::~Etudiant()" << endl;} }; int main() { Personne * p1 = new Etudiant("GAMOTTE","Albert",34,'M',13); p1->Affiche(); delete p1; }

116

Fonction/Mthode virtuelle et typage dynamique (3/9)


class Etudiant : public Personne { int note; public: // Constructeur Etudiant(string nm, string p, int a, char s, int n):Personne(nm,p,a,s) { note = n; cout << "Etudiant::Etudiant(" <<GetNom()<< "," << GetPrenom() << ","<< GetAge() << "," << GetSexe() << "," << note << ")" << endl; } void Affiche() // Affichage { Personne::Affiche(); cout << "Il s'agit d'un tudiant ayant pour note :" << note << "." << endl; } // Destructeur ~Etudiant() {cout << "Etudiant::~Etudiant()" << endl;} }; int main() { Personne * p1 = new Etudiant("GAMOTTE","Albert",34,'M',13); p1->Affiche(); Personne::Personne(GAMOTTE,Albert,34,M) delete p1; Etudiant::Etudiant(GAMOTTE,Albert,34,M,13) } Monsieur Albert GAMOTTE ag de 34 ans. Personne::~Personne()

116

Fonction/Mthode virtuelle et typage dynamique (3/9)


class Etudiant : public Personne { int note; public: // Constructeur Etudiant(string nm, string p, int a, char s, int n):Personne(nm,p,a,s) { note = n; cout << "Etudiant::Etudiant(" <<GetNom()<< "," << GetPrenom() << ","<< GetAge() << "," << GetSexe() << "," << note << ")" << endl; } void Affiche() // Affichage { Personne::Affiche(); cout << "Il s'agit d'un tudiant ayant pour note :" << note << "." << endl; } // Destructeur ~Etudiant() {cout << "Etudiant::~Etudiant()" << endl;} };

int main() { Personne * p1 = new Etudiant("GAMOTTE","Albert",34,'M',13); p1->Affiche(); Personne::Personne(GAMOTTE,Albert,34,M) delete p1; Etudiant::Etudiant(GAMOTTE,Albert,34,M,13) } Monsieur Albert GAMOTTE ag de 34 ans. Personne::~Personne()

// Pas dappel de la mthode Affiche() ou du // destructeur de la classe Etudiant

116

Fonction/Mthode virtuelle et typage dynamique (4/9)


class Personne { string nom; string prenom; int age; char sexe; public : // Constructeur Personne(string n, string p, int a, char s) { nom=n; prenom=p; age=a; sexe=s; cout << "Personne::Personne("<<nom<< "," << prenom << "," << age << "," << sexe << ")" } virtual void Affiche() // Affichage { if (sexe == 'M') cout << "Monsieur " else cout << "Madame/Mademoiselle " ; cout << prenom << " " << nom << " age de " << age << " ans." << endl; } // Destructeur virtual ~Personne() {cout << "Personne::~Personne()" << endl;} };

<< endl;

117

Fonction/Mthode virtuelle et typage dynamique (4/9)


class Personne { string nom; string prenom; int age; char sexe; public : // Constructeur Personne(string n, string p, int a, char s) { nom=n; prenom=p; age=a; sexe=s; cout << "Personne::Personne("<<nom<< "," << prenom << "," << age << "," << sexe << ")" } virtual void Affiche() // Affichage { if (sexe == 'M') cout << "Monsieur " else cout << "Madame/Mademoiselle " ; cout << prenom << " " << nom << " age de " << age << " ans." << endl; } // Destructeur virtual ~Personne() {cout << "Personne::~Personne()" << endl;} };

<< endl;

117

Fonction/Mthode virtuelle et typage dynamique (5/9)


int main() { Personne * p1 = new Etudiant("GAMOTTE","Albert",34,'M',13); // Appel de la mthode Affiche() de la classe Etudiant // La mthode tant virtuelle dans la classe Personne p1->Affiche(); // Appel du destructeur de la classe Etudiant // qui appelle celui de la classe Personne delete p1; }

Personne::Personne(GAMOTTE,Albert,34,M) Etudiant::Etudiant(GAMOTTE,Albert,34,M,13) Monsieur Albert GAMOTTE ag de 34 ans. Il s'agit d'un tudiant ayant pour note :13. Etudiant::~Etudiant() Personne::~Personne()

118

Fonction/Mthode virtuelle et typage dynamique (6/9)


Toujours dclarer virtuel le destructeur dune classe de base destine tre drive pour sassurer que une libration complte de la mmoire Pas dobligation de redfinir une mthode virtuelle dans les classes drives Possibilit de redfinir une mthode virtuelle dune classe de base, par une mthode virtuelle ou non virtuelle dans une classe drive Ncessit de respecter le prototype de la mthode virtuelle redfinie dans une classe drive (mme argument et mme type retour) 119

Fonction/Mthode virtuelle et typage dynamique (6/9)

Toujours dclarer virtuel le destructeur dune classe de base destine tre drive pour sassurer que une libration complte de la mmoire Pas dobligation de redfinir une mthode virtuelle dans les classes drives Possibilit de redfinir une mthode virtuelle dune classe de base, par une mthode virtuelle ou non virtuelle dans une classe drive Ncessit de respecter le prototype de la mthode virtuelle redfinie dans une classe drive (mme argument et mme type retour) 119

Fonction/Mthode virtuelle et typage dynamique (7/9)


Possibilit didentifier et de comparer lexcution le type dun objets dsign par un pointeur ou une rfrence Oprateur typeid permettant de rcuprer les informations de type des expressions Informations de type enregistres dans des objets de la classe type_info
Classe prdfinie dans l'espace de nommage std Classe offrant des oprateurs de comparaison de type (== et !=) et une mthode name() retournant une chane de caractres reprsentant le nom du type ! Format des noms de types pouvant varier d'une implmentation une autre (pas de norme)

120

Fonction/Mthode virtuelle et typage dynamique (8/9)


// Exemple repris de [Delannoy, 2004] #include <iostream> #include <typeinfo> // pour typeid using namespace std ; class point { public : virtual void affiche () { } // ici vide // utile pour le polymorphisme } ; class pointcol : public point { public : void affiche () { } // ici vide } ; int main() { point p ; pointcol pc point * adp ; adp = &p ; cout << "type de adp cout << "type de *adp adp = &pc ; cout << "type de adp cout << "type de *adp } ; : " << typeid (adp).name() << endl ; : " << typeid (*adp).name() << endl ; : " << typeid (adp).name() << endl ; : " << typeid (*adp).name() << endl ;

121

Fonction/Mthode virtuelle et typage dynamique (8/9)


// Exemple repris de [Delannoy, 2004] #include <iostream> #include <typeinfo> // pour typeid using namespace std ; class point { public : virtual void affiche () { } // ici vide // utile pour le polymorphisme } ; class pointcol : public point { public : void affiche () { } // ici vide } ; int main() { point p ; pointcol pc point * adp ; adp = &p ; cout << "type de adp cout << "type de *adp adp = &pc ; cout << "type de adp cout << "type de *adp } ; type type type type de de de de adp *adp adp *adp : : : : P5point 5point P5point 8pointcol

: " << typeid (adp).name() << endl ; : " << typeid (*adp).name() << endl ; : " << typeid (adp).name() << endl ; : " << typeid (*adp).name() << endl ;

121

Fonction/Mthode virtuelle et typage dynamique (9/9)


// Exemple repris de [Delannoy, 2004] int main() { point p1, p2 ; pointcol pc ; point * adp1, * adp2 ; adp1 = &p1 ; adp2 = &p2 ; cout << "En A : les objets pointes par adp1 et adp2 sont de " ; if (typeid(*adp1) == typeid (*adp2)) cout << "meme type" << endl ; else cout << "type different" << endl; adp1 = &p1 ; adp2 = &pc ; cout << "En B : les objets pointes par adp1 et adp2 sont de " ; if (typeid(*adp1) == typeid (*adp2)) cout << "meme type" << endl ; else cout << "type different" << endl; }

122

Fonction/Mthode virtuelle et typage dynamique (9/9)


// Exemple repris de [Delannoy, 2004] int main() { point p1, p2 ; pointcol pc ; point * adp1, * adp2 ; adp1 = &p1 ; adp2 = &p2 ; cout << "En A : les objets pointes par adp1 et adp2 sont de " ; if (typeid(*adp1) == typeid (*adp2)) cout << "meme type" << endl ; else cout << "type different" << endl; adp1 = &p1 ; adp2 = &pc ; cout << "En B : les objets pointes par adp1 et adp2 sont de " ; if (typeid(*adp1) == typeid (*adp2)) cout << "meme type" << endl ; else cout << "type different" << endl; }

En A : les objets pointes par adp1 et adp2 sont de meme type En B : les objets pointes par adp1 et adp2 sont de type different

122