---
# System prepended metadata

title: Cour 6 -- Language Orienté Objet avancé (C++)
tags: [M1 S1, cpp, cour]

---

# 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)