# Cour 5 -- Language Orienté Objet avancé (C++)
###### tags `cour` `M1 S1` `cpp`
[Somaire](/V1WXmN9oTdauw8pTXPhqrQ)\
[Precedent](/xWa96-AGQI6G__rHTzd0Tg)
> [time= 12 oct 2020]
[TOC]
## association
### ordinaire

On peut faire de l'association ordinaire en utilisatant juste des pointeur vers notre objet en relation.
```cpp=
class Vol
{
private:
Personne **passagers;
int nPassagers;
public:
void prendUnPassagerEnPlus(Personne &);
bool aPourPassager(const Personne &);
};
class Personne
{
private:
Vol **vols;
int nVols;
public:
void sEnregistreDansLeVol(Vol &);
bool estPassagerDuVol(const Vol &);
};
void Personne::sEnregistreDansLeVol(Vol &leVol)
{
if (this->estPassagerDuVol(leVol))
return;
add(vols,nvols,leVol);
leVol.prendUnPassagerEnPlus(*this);
}
void Vol::prendUnPassagerEnPlus(Personne &lePassager)
{
if (this->aPourPassager(lePassager))
return; add(passagers,nPassagers,lePassager);
lePassager.sEnregistreDansLeVol(*this);
}
```
### class d'association
Au lieu de mettre la relation dans les classe diretement.
On utilise une class externe, avec une méthod static.

```cpp=
class Personne
{
void addVol(const Vol &v)
{
RelationVolPassager::add(v,*this);
}
};
class Vol
{
void addPassager(const Personne &p)
{
RelationVolPassager::add(*this,p);
}
};
class RelationVolPassager {
friend class Vol;
friend class Personne;
private:
static void add(const Vol &,const Personne &);
};
```
## agrégation (simple)
On utilise une liste d'objet avec référence ou pointeur

```cpp=
class Evenement
{};
class Historique
{
private:
const Evenement **lesEvenements;
int nEvenement;
public:
void addEvenement(const Evenement &);
void removeEvenement(const Evenement &);
Evenement *getEvenementAt(int);
...
};
```
## composition
On ajoute objet ou tableau d'objet un champ (sans pointeur ou référence)

```cpp=
class F3 {
private:
class Piece {};
Piece pieces[3];
};
```
## généralisation / spécialisation
- généralisation vers le parent
- spécialisation vers l'enfant
```
[ véhicule ]
^
généralisation | spécialisation
|
[ voiture ]
```
| Conception | language |
|:--------------:|:-------------------:|
| relation | - champ |
| relation | class d'association |
| | |
| Spécialisation | héritage |
| Spécialisation | délégation |
## spécialisation
On peut utiliser l'héritage.
- on crée un héritage avec `class MaCall: public Parent`
- on peut **redéfinir** une méthode en la réecrivant
- pour récupéré une méthode de la classe du dessus on utilise le nom de la méthode `Parent::méthod`
- initialisation, on utilise les contructeur de la class parent dans la list d'initialisation (`super` en java est remplacé par le nom de la class)
- attention a initialiser les class du dessus avant
- la destruction se fait dans le sens inverse
### redéfinition vs surcharge
:::success
**surcharge** dans le context on redéfini une meme fonction (en changeant le nombre d'argument ou les types)
:::
```cpp=
class A
{
public:
void m1(int i);
void m1(char f); // surcharge
void m2(int i);
void m2(char c); // surcharge
};
```
:::success
**redifinition** on utilise un sybole déja utilisé
:::
```cpp=+
class B : public A {
public:
void m1(int i); //redéfinition dans B par rapport a A
void m1(float f); //surcharge
};
```
## visibilité
rapelle:
- private
- visible **uniquement** depuis les fonctions membres de la **classe**
- public
- visible depuis **n’importe quelle partie du code**
- protected:
- comme privé mais disponible dans les **dérivations**
| Protection dans la classe de base | accessibilité dans une fonction membre de la classe dérivée | Accessibilité dans une fonction amie de la sous- classe | Accessibilité par utilisation de la classe dérivée (hors cas précédents) |
|:---------------------------------:|:-----------------------------------------------------------:|:-------------------------------------------------------:|:------------------------------------------------------------------------:|
| **private** | :x: | :x: | :x: |
| **protected** | :white_check_mark: | :white_check_mark: | :x: |
| **public** | :white_check_mark: | :white_check_mark: | |
toujours mettre les champs en privé
et mettre les methodes getter setter ne protected
## compatibilité des types
- on peut toujours convertir une instance d'une class donnée en un objet de sa super-classe
- on a de l'object slicing
```cpp=
class DeBase
{...};
class SousClasse : public DeBase
{...};
class BienEnDessous : public SousClasse
{...};
int main()
{
BienEnDessous unObjet;
DeBase unObjetDeBase = unObjet;
//unObjet = unObjetDeBase; // strictly forbidden...
BienEnDessous *p = &unObjet;
DeBase *p2;
p2 = p;
//p = p2; // formellement interdit
}
```
### liaison tardive (dynamique)
l’appel à une méthode qualifiée de virtuelle (`virtual`) provoquera à l’exécution la recherche de la méthode appropriée - late binding
C'est du polymorphisme par sous typage
```cpp=
class DeBase
{
public:
virtual void f()
{
cout << “DeBase“ << endl;
}
};
class SousClasse : public DeBase
{
public:
virtual void f()
{
cout << “SousClasse“ << endl;
}
};
void uneFonction(DeBase &o)
{
o.f();
}
int main()
{
SousClasse unObjet;
unObjet.f();
DeBase instanceDeBase = unObjet;
instanceDeBase.f();
SousClasse *pSousClasse = &unObjet;
pSousClasse->f();
DeBase *pBase = pSousClasse;
pBase->f();
uneFonction(unObjet);
return 0;
}
```
sortie:
```
SousClasse
DeBase
SousClasse
SousClasse
SousClasse
```
[suivant](/cGQPtmoaTZSwx3NaECxuHg)