La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Programmation en C++ Héritage

Présentations similaires


Présentation au sujet: "Programmation en C++ Héritage"— Transcription de la présentation:

1 Programmation en C++ Héritage
Conception Exemple de classes Fonctions virtuelles Fonctions virtuelles pures Classes abstraites

2 Rappel: Relations entre les classes « Hérite »
La relation « Hérite » (“Inheritance“) Une classe (A) peut hériter de l'état (des variables) et du comportement (des méthodes) d'une autre classe (B) On dit que la classe A représente un super-type (super-classe) de la classe B, représentant un sous-type (sous-classe) Ou que la classe A représente une généralisation de la classe B, représentant une spécialisation de la classe A Ou que la classe A représente une classe de base de la classe B, représentant une classe dérivée de la classe A Par exemple un vélo de montagne, un vélo de route ou un vélo tandem sont tous du type vélo Vélo Vélo de montagne Vélo de route Vélo tandem

3 Exemple Pour démontrer la conception et l'implantation de l'héritage nous allons développer des classes qui décrivent les animaux de compagnie dans une famille française habituelle Essayons de trouver des caractéristiques communes pour nos animaux typiques – le chat et le chien Chacun a son nom Il faut qu'on leur donne à manger – ils mangent Il nous parlent – le chien aboie, le chat miaule Les comportements spécifiques: Le chat chasse les souris Le chien monte la garde de la maison

4 La conception ... Chien nom Mange() Parle() MonteLaGarde() Chat nom Mange() Parle() ChasseSouris() ADC nom Mange() Parle() Les données membres et les fonctions communes peuvent être extraites dans une super-classe (ou classe de base) ADC (= Animal de compagnie)

5 ... La conception ADC nom Mange() Parle() Chien Chat MonteLaGarde()
ChasseSouris()

6 Les Classes (définition)
#include <string> class ADC { public: ADC(std::string nom); void Mange(); void Parle(); std::string Nom(); private: std::string m_nom; }; #include “ADC.h” #include <string>  class Chien : public ADC { public: Chien(std::string nom); void MonteLaGarde(); }; La déclaration de la relation de l'héritage #include “ADC.h” #include <string>  class Chat : public ADC { public: Chat(std::string nom); void ChasseSouris(); }; ADC nom Mange() Parle() Chien MonteLaGarde() Chat ChasseSouris()

7 Les Classes (implantation)
#include "ADC.h" #include <iostream> ADC::ADC(std::string nom) : m_nom(nom) { } void ADC::Mange() { std::cout << m_nom << " mange" << std::endl; void ADC::Parle() { std::cout << m_nom << " parle" << std::endl; std::string ADC::Nom() { return m_nom; #include "Chien.h" #include <iostream> Chien::Chien(std::string nom) : ADC(nom) { } void Chien::MonteLaGarde() { std::cout << Nom() << " monte la garde " << std::endl; #include "Chat.h" #include <iostream> Chat::Chat(std::string nom) : ADC(nom) { } void Chat::ChasseSouris() { std::cout << Nom() << " chasse la souris " << std::endl; ADC nom Mange() Parle() Chien MonteLaGarde() Chat ChasseSouris() Initialisation de la classe de base (super-classe)

8 Les Classes (utilisation) ...
#include "Chien.h" #include "Chat.h" int main() { Chien chien("Bella"); Chat chat("Minette"); // Quand on arrive a la maison les ADCs nous font // la fête chien.Parle(); chat.Parle(); // Il faut leur donner à manger chien.Mange(); chat.Mange(); // Et tout le monde s'occupe de son travail chien.MonteLaGarde(); chat.ChasseSouris(); } main.cxx Déclaration des objets avec leurs types spécifiques (par des sous-classes) Appel de fonctions définies dans la classe de base Appel de fonctions définies dans les sous-classes [localhost]> ./chezNous Bella parle Minette parle Bella mange Minette mange Bella monte la garde Minette chasse une souris

9 ... Les Classes (utilisation)
#include "Chien.h" #include "Chat.h" int main() { Chien chien("Bella"); Chat chat("Minette"); ADC& adc1 = chien; ADC& adc2 = chat // Quand on arrive a la maison les ADCs nous font // la fête adc1.Parle(); adc2.Parle(); // Il faut leur donner à manger adc1.Mange(); adc2.Mange(); // Et tout le monde s'occupe de son travail chien.MonteLaGarde(); chat.ChasseSouris(); } main2.cxx Déclaration des objets avec le type générique (par la super-classe) Appel de fonctions définies dans la classe de base Appel de fonctions définies dans les sous-classes [localhost]> ./chezNous2 Bella parle Minette parle Bella mange Minette mange Bella monte la garde Minette chasse une souris

10 Après 1. étape La classe de base (ADC)
implante la donnée membre commune Les sous-classes (Chien, Chat) héritent l'état implante des méthodes communes Les sous-classe (Chien, Chat) héritent de l'implantation des méthodes L'introduction de la classe de base nous a évité la duplication du code commun aux sous-classes

11 Spécialisation de fonctions ...
Nous allons préciser notre modèle: Le chien mange des croquettes ProPlan Le chat mange des boites Whiskas Le chien aboie Le chat miaule Modélisation: ADC nom Mange() Parle() Chaque sous-classe redéfinit des fonctions de la classe de base Chien Mange() Parle() MonteLaGarde() Chat Mange() Parle() ChasseSouris()

12 ... Spécialisation de fonctions ...
Nous allons ajouter ces méthodes à des classes Chien, Chat: ADC nom Mange() Parle() #include “ADC.h” #include <string>  class Chien : public ADC { public: Chien(std::string nom); void Mange(); void Parle(); void MonteLaGarde(); }; #include “ADC.h” #include <string>  class Chat : public ADC { public: Chat(std::string nom); void Mange(); void Parle(); void ChasseSouri(); }; Chien Mange() Parle() MonteLaGarde() Chat Mange() Parle() ChasseSouris() Chien::Mange() { std::cout << nom() << " mange des croquettes ProPlan " << std::endl; } void Chien::Parle() { std::cout << Nom() << ": wouaf, wouaf !! " << std::endl; Chat::Mange() { std::cout << nom() << " mange des boites Whiskas " << std::endl; } void Chat::Parle() { std::cout << Nom() << ": miaou, miaou !! " << std::endl; La déclaration de la relation de héritage

13 ... Spécialisation de fonctions
On compile et exécute les deux programmes: [localhost] > ./chezNous Bella: wouaf, wouaf !!! Minette: miaou, miaou !!! Bella mange des croquettes ProPlan Minette mange des boites Whiskas Bella monte la garde Minette chasse une souris Si déclaration des objets avec leur types spécifiques (par des sous-classes) OK [localhost]> ./chezNous2 Bella parle Minette parle Bella mange Minette mange Bella monte la garde Minette chasse une souri Si déclaration des objets avec le type générique (par la super-classe) FAUX !!! ou plutôt ce n'est pas ce que nous voulions obtenir ...

14 Fonctions virtuelles ... Pour que la « bonne » fonction soit appelée il faut la déclarer virtual La « bonne » fonction = la fonction définie pour la classe dont le type dynamique de notre objet est L'objet défini par la référence adc1 est du type Chien, adc2 du type Chat La fonction virtuelle agit comme une interface pour les fonctions définies dans la classe de base et dans toutes les classes dérivées #include <string> class ADC { public: ADC(std::string nom); virtual void Mange(); virtual void Parle(); private: std::string m_nom; }; #include “ADC.h” #include <string>  class Chien : public ADC { public: Chien(std::string nom); virtual void Mange(); virtual void Parle(); void MonteLaGarde(); }; #include “ADC.h” #include <string>  class Chat : public ADC { public: Chat(std::string nom); virtual void Mange(); virtual void Parle(); void ChasseSouri(); }; Fonction déclarée virtuelle Il n'est pas obligatoire de re-déclarer les fonctions virtuelles dans des classes dérivées mais c'est une bonne pratique de le faire La déclaration de la relation de héritage

15 ... Fonctions virtuelles On compile et exécute les deux programmes de nouveau: [localhost] > ./chezNous Bella: wouaf, wouaf !!! Minette: miaou, miaou !!! Bella mange des croquettes ProPlan Minette mange des boites Whiskas Bella monte la garde Minette chasse une souris Si déclaration des objets avec leur types spécifiques (par des sous-classes) OK [localhost]> ./chezNous2 Bella: wouaf, wouaf !!! Minette: miaou, miaou !!! Bella mange des croquettes ProPlan Minette mange des boites Whiskas Bella monte la garde Minette chasse une souris Si déclaration des objets avec le type générique (par la super-classe) OK

16 Les Classes (utilisation)
main3.cxx L'existence de la classe de base nous permet de nous adresser à nos objets de façon générique #include "Chien.h" #include "Chat.h" #include <vector> int main() { Chien* chien = new Chien("Bella"); Chat* chat = new Chat("Minette"); // La collection des nos animaux std::vector<ADC*> nosAnimaux; nosAnimaux.push_back(chien); nosAnimaux.push_back(chat); // Quand on arrive a la maison les ADCs nous font la fête std::vector<ADC*>::iterator it; for ( it=nosAnimaux.begin(); it != nosAnimaux.end(); it++ ) (*it)->Parle(); // Il faut leur donner a manger (*it)->Mange(); // Et tout le monde s'occupe de son travail chien->MonteLaGarde(); chat->ChasseSouris(); } Les fonctions spécifiques ne peuvent pas être appelées de façon générique [localhost]> ./chezNous3 Bella: wouaf, wouaf !!! Minette: miaou, miaou !!! Bella mange des croquettes ProPlan Minette mange des boites Whiskas Bella monte la garde Minette chasse une souris

17 Si on achète un canari On ajoute une nouvelle classe dérivée de la classe ADC: #include “ADC.h” #include <string>  class Canari : public ADC { public: Canari(std::string nom); }; #include "Canari.h" #include <iostream> Canari::Canari(std::string nom) : ADC(nom) { } main4.cxx // ... #include "Canari.h" int main() { Canari* canari = new Canari("Lori"); nosAnimaux.push_back(canari); } [localhost]> ./chezNous4 Bella: wouaf, wouaf !!! Minette: miau, miau !!! Lori parle Bella mange des croquettes ProPlan Minette mange des boites Whiskas Lori mange Bella monte la garde Minette chasse une souris

18 Après 2. étape La classe de base (ADC)
implante la donnée membre commune Les sous-classes (Chien, Chat) héritent de l'état définit l'interface pour des méthodes communes Les sous-classes (Chien, Chat) héritent de l'interface des méthodes et fournissent leurs propres définitions (implantations) implante des méthodes communes Les classes qui ne fournissent pas leurs propres définitions, ou implantations, (Canari) vont utiliser celles définies par la classe de base La classe de base nous permet d'appeler les fonctions propres aux objets par l'interface commune

19 3. étape Nous allons de nouveau ré-examiner les exigences de notre programme Imaginons que nous allons confier nos bêtes à notre voisin et lui demander de nous remplacer pendant nos vacances Notre programme l'aidera à savoir les besoins de nos animaux: Mais qu'est-ce que mange Lori? Notre classe de base nous a permis de ne pas spécifier les besoins de notre canari [localhost]> ./chezNous4 Bella: wouaf, wouaf !!! Minette: miau, miau !!! Lori parle Bella mange des croquettes ProPlan Minette mange des boites Whiskas Lori mange Bella monte la garde Minette chasse une souris

20 Fonctions virtuelles pures
La classe de base peut obliger toutes les classes dérivées à implanter une fonction si elle la déclare comme une fonction virtuelle pure: #include "ADC.h" #include <iostream> ADC::ADC(std::string nom) : m_nom(nom) { } void ADC::Mange() { std::cout << m_nom << " mange" << std::endl; void ADC::Parle() { std::cout << m_nom << " parle" << std::endl; std::string ADC::Nom() { return m_nom; #include <string> class ADC { public: ADC(std::string nom); virtual void Mange() = 0; virtual void Parle() = 0; private: std::string m_nom; }; Fonctions déclarées virtuelle pure Les fonctions virtuelles pures n'ont pas la definition (l'implantation)

21 ... Fonctions virtuelles pures
On compile notre programme ... et il ne se compile pas ! Il est impossible de créer une instance de la classe qui n'a pas défini toutes les fonctions virtuelles pures héritées ainsi que de la classe qui a déclaré une fonction virtuelle Les classes desquelles on ne peut pas créer d' instance s'appellent les classes abstraites [localhost] > g++ -I. *.cxx -o chezNous4 main4.cxx: In function ‘int main()’: main4.cxx:10: error: cannot allocate an object of abstract type ‘Canari’ Canari.h:4: note: because the following virtual functions are pure within ‘Canari’: ADC.h:10: note: virtual void ADC::Mange() ADC.h:11: note: virtual void ADC::Parle()

22 Après 3. étape La classe de base (ADC)
implante la donnée membre commune Les sous-classes (Chien, Chat) héritent de l'état définit l'interface pour des méthodes communes obligatoires Toutes les sous-classes (Chien, Chat, Canari) sont obligées de fournir leurs propres définitions (implantations) devient abstraite Il est impossible de créer une instance de la classe ADC La classe de base nous garantit que toutes les classes dérivées implantent les interfaces obligatoires

23 Si on nous donne un lapin ...
Il faut ajouter le lapin dans notre famille de classes ADC Il faut alors définir des fonctions: Mange() - ok, le lapin mange des herbes sèches Parle() mais le lapin ne parle pas ! Notre conception de la classe ADC n'était pas assez générique, comme la fonction Parle() n'est pas propre à tous animaux

24 ... Si on nous donne un lapin
On peut toujours définir la fonction et laisser le programme nous prévenir que la fonction qui a été appelée n'a pas de sens pour notre objet On peut évaluer la conception pour mieux refléter la réalité void Lapin::Parle() { std::cout << “Mais “ << Nom() << " ne parle pas !! " << std::endl; } ADC nom Mange() Classe des animaux de compagnie qui parlent ADCP Parle() Chien Mange() Parle() MonteLaGarde() Chat ChasseSouris() Chat ChasseSouris() Chat ChasseSouris() Chat Mange() Parle() ChasseSouris() Chat ChasseSouris() Chat ChasseSouris() Chat ChasseSouris() Canari Mange() Parle() Chat ChasseSouris() Lapin Mange() Chat ChasseSouris() Chat ChasseSouris()


Télécharger ppt "Programmation en C++ Héritage"

Présentations similaires


Annonces Google