# Cour 6 -- Language Orienté Objet avancé (C++) ###### tags `cour` `M1 S1` `cpp` [Somaire](/V1WXmN9oTdauw8pTXPhqrQ)\ [Precedent](/xWa96-AGQI6G__rHTzd0Tg) > [time= 19 oct 2020] [TOC] ## héritage ### constructeur de copy ```cpp= class A { public: A() { cout << "A()" << endl; } A(const A &a) { cout << "A(const A&)" << endl; } }; class B : public A { public: B() { cout << "B()" << endl; } B(const B &b) :A(b){ cout << "B(const &B)" << endl; } // add explicit A(b) }; void f(B unObjet) { } int main() { B b; cout << "Appel a f(B)" << endl; f(b); return 0; } ``` ```shell= $ ./main A() B() Appel a f(B) A(const A&) # apelle au constructeur de copy B(const &B) ``` ### sous-typage (héritage privé) On peut faire une composition en faisant de l'hérigage privé. Mais on préfaire **utiliser l'heritage simple**. ### composition classique ```cpp= class Moteur { public: void demarre() { ... }; }; class Voiture { private: Moteur leMoteur; public: void demarre() { leMoteur.demarre(); } }; ``` ### composition par hériage privé ```cpp= class Moteur { public: void demarre() { ... }; }; class Voiture : private Moteur { public: void demarre() { Moteur::demarre(); } } ``` ### hériage protégé Son usage est tres rare. ![](https://i.imgur.com/Iu4eEIM.png) ## factorisation Quand on voit que des objet ont des méthode commune on factorise. C'est un peut un mode d'emploie. ![](https://i.imgur.com/LfrmDGf.png) - On utilise des fleche avec des pointillé - fleche pleine pour les relations entre interface en étend un autre On crée donc une classe interface avec des virtuelle pure (`virtual method = 0;`).\ Ce qui est équivalent abstract en Java ## factorisation d'implémentation On va faire apparaitre des class abstraite. On peut spécifié `_impl` pour dire que c'est une classe d'implémentation. ```cpp= class Individu { public: virtual string donneTonNom()=0; virtual void prononceTonNom()=0; }; class _Individu : public Individu { private: string nom; protected: void prononceTonNom(mode m) { synthétiseurVocal.setMode(m); synthétiseurVocal.synthetise(donneTonNom()); } public: virtual string donneTonNom() { return nom; } }; class Homme : public _Individu { public: virtual void prononceTonNom() { prononceTonNom(GRAVE); } }; class Femme : public _Individu { public: virtual void prononceTonNom() { prononceTonNom(AIGU); } }; ``` ## conversion polymorphe - upcast (conversion vers le haut) `static_cast<type>()` - objet - pointeur - référence - dowcast (conversion vers le bas) `dynamic_cast<type>()` - impossible sur les objet - à controler sur les pointeurs - à controler sur les reférence `dynamic_cast<type>`: - permet d’obtenir une conversion vers un sous-type (downcast) - un pointeur nul (0) si la conversion n’est pas correcte - une exception (bad_cast) si la référence n’est pas correcte ## RTTI Pour faire du RTTI il faut laisser des types apres la compilation. Utiliser souvent pour debug. On utilise `typeid(type)` ou `typeid(expr)`. On récupere un objet de type: `type_info`. - On peut les comparé avec `==` - On peut récupéré le nom de type avec la méthode `name` - ce type n’est pas instanciable ni copiable A utiliser **que pour debug**, on ne produit pas de code, avec du RTTI! ## Héritage multiple ### compostion multiple On peut vouloir utiliser l'héritage multiple pour faire de la composition multiple. Il vaut mieux utilisr la compostion simple. #### par héritage multiple ```cpp= class Magnetophone { public: void demarreEcoute() { ... }; void demarreEnregistrement() { ... }; }; class Camera { public: void demarreProjection() { ... }; void demarreEnregistrement() { ... }; }; ``` ```cpp=+ class Camescope : private Magnetophone, private Camera { public: void enregistreFilm() { Magnetophone::demarreEnregistrement(); Camera::demarreEnregistrement(); } void regardeFilm() { Magnetophone::demarreEcoute(); Camera::demarreProjection(); } }; ``` ### version classique **il vaut mieux utiliser cette méthode** ```cpp=+ class Camescope { private: Magnetophone m; Camera c; public: void enregistreFilm() { m.demarreEnregistrement(); c.demarreEnregistrement(); } void regardeFilm() { m.demarreEcoute(); c.demarreProjection(); } }; ``` ### génélisation multiple Exemple de d'objet avec un généralisation multiple: - l'hornitorique - l'hidravioon ![](https://i.imgur.com/01WpKrR.png) ```cpp= class Imprimable { public: virtual void imprimer()=0; }; class Editable { public: virtual void editer()=0; }; class CourrierElectroniqueRecu : virtual public Imprimable { public: virtual void imprimer() { /* just do it... */} }; class DocumentPDF : virtual public Imprimable, virtual public Editable { public: virtual void editer() { /* do your best... */ } virtual void imprimer() { /* merci Johannes Gensfleisch * zur Laden zum Gutenberg */ } }; ``` ### Probleme? - Aucun problème théorique \ car on hérite de rien (ou presque), i.e. pas d’implémentation, tout est abstrait - Seul problème pratique, l’éventuel **conflit de nom** - deux super-types utilisent un même nom... - si les actions sont différentes on a un probleme ![](https://i.imgur.com/VvsaZ0f.png) ```cpp= class IPoint { public: virtual void affiche() = 0; }; class ICouleur { public: virtual void affiche() = 0; }; class PointColore : virtual public IPoint, virtual public ICouleur { public: virtual void affiche() { /* OK */ } }; ``` ##### Construction en diamand ```cpp= class Base { public: Base(int v) {} }; class Classe1 : virtual public Base { public: Classe1() : Base(3) {} // N’est appelé que si la partie Base n’existe pas... }; class Classe2 : virtual public Base { public: Classe2() : Base(5) {} // N’est appelé que si la partie Base n’existe pas... }; class ToutEnBas : virtual public Base, virtual public Classe1, virtual public Classe2 { public: ToutEnBas() : Base(4), Classe1(), Classe2() {} }; ``` ### le typage Comme précédement. Mais attention au dynamic_cast qui change les adresses. Donc ne pas se fié au adresse comme identifiant ### conseil - N’utilisez pas l’héritage multiple pour faire de la composition - Réservez-le uniquement pour la généralisation multiple - Déclarez toutes les méthodes virtuelles - Déclarez tous les héritages comme virtuels - Ne comptez plus sur l’adresse comme identifiant de l’objet ## surcharge d'opérateur On peut surcharger quasiment tout les opérateur en c++; [suivant](/NP4jzSxKSPy2sv9RsWcB2Q)