Héritage.

Héritage de classes.

Voir version :

Pas de dépendances

Télécharger :

#include <iostream>
#include <cstdlib>

using namespace std;


class Vaisseau
{
protected:
    int a;
public:
    Vaisseau() {cout << "Vaisseau::Vaisseau" << endl;}
    ~Vaisseau(){cout << "Vaisseau::~Vaisseau" << endl;}
    void plouf(){cout << "Vaisseau::plouf" << endl;}
    void test_vaisseau()
    {
        a=1;
        cout << "Vaisseau::test_vaisseau" << endl;
    }
};

class LanceMissile:public Vaisseau
{
protected:
    int b;
public:
    LanceMissile(){cout << "LanceMissile::LanceMissile" << endl;}
    ~LanceMissile(){cout << "LanceMissile::~LanceMissile" << endl;}
    void plouf(){cout << "LanceMissile::plouf" << endl;}
    void test_lancemissile()
    {
        a=2;
        b=3;
        cout << "LanceMissile::test_lancemissile" << endl;
    }
};

class MantaShip:public LanceMissile
{
protected:
    int c;
public:
    MantaShip(){cout << "MantaShip::MantaShip" << endl;}
    ~MantaShip(){cout << "MantaShip::~MantaShip" << endl;}
    void plouf(){cout << "MantaShip::plouf" << endl;}
    void test_mantaship()
    {
        a=4;
        b=5;
        c=6;
        cout << "MantaShip::test_mantaship" << endl;
    }
    void testheritagesecurit()
    {
        test_lancemissile();
        test_vaisseau();
    }
};


void fonc()
{
    cout << "infonc" << endl;
    MantaShip m;
    m.plouf();
    m.test_mantaship();
    m.test_lancemissile();
    m.test_vaisseau();
    cout << "fin fonc" << endl;
}

void fonc2()
{
    cout << "infonc2" << endl;
    LanceMissile m;
    m.plouf();
    //m.Vaisseau::plouf();
    m.test_lancemissile();
    m.test_vaisseau();
    cout << "fin fonc2" << endl;
}

void fonc3()
{
    cout << "infonc3" << endl;
    Vaisseau m;
    //m.a = 5;
    m.plouf();
    m.test_vaisseau();
    cout << "fin fonc3" << endl;
}

int main()
{
    fonc();
    fonc2();
    fonc3();
    system("pause");
    return 0;
}



Commentaires


  Notion d'héritage.
  Ce tuto est en 2 parties.

  D'abord, il montre l'héritage pour les débutants, ensuite, quelques tests rigolos pour ceux qui veulent

Notion pour détants :
*********************

  On va dire qu'un vaisseau, c'est un truc assez général.
  Un Lance Missile, c'est un vaisseau, mais avec des particularités en plus
  Un Manta, c'est un Lance Missile, mais avec des particularités en plus.

  On défini une classe Vaisseau, avec  les particularités générales d'un vaisseau
  On met ses données "privées" en protected.

  C'est a dire, que si dans fonc3(), on fait m.a = 5 (voir ligne commentée), alors on se fait arreter a la compilation
  En effet, a est protégé, donc on ne peut pas la piloter de l'extérieur.

  LanceMissile hérite de Vaisseau.
  Il hérite aussi de ses données protégées : donc, dans test_lancemissile, la ligne a=2 est tolérée.

  test : 
  remplacez, dans vaisseau, protected par private.
  la ligne a=2 est maintenant interdite :

  - protected protege les données pour la classe, et ses héritieres.
  - private protege les données pour la classe UNIQUEMENT (donc pour vaisseau, pas "lancemissile")

  Pour débutants : pour déclarer un héritage, utilisez public comme ceci :
  class LanceMissile:public Vaisseau


// fonctions définies dans meres et filles, comment choisir ?
-------------------------------------------------------------

  L'appel de "plouf" :

  Comme vous le voyez, la fonction plouf est définie dans chaque classe.
  Quand, dans une classe fille, vous redefinissez une fonction de la mere, alors c'est celle de la fille qui est appelée.
  (vous le voyez en lançant le programme, les fonctions ont toute un cout, pour montrer ou on passe)

  Vous pouvez néanmoins toujours appeler explicitement la fonction plouf de la mere ainsi :
  m.Vaisseau::plouf();  (décomentez la ligne dans fonc2)



Notions plus avancées
*********************

  Tous les héritages présentés sont publiques

  Remplacer public par protected dans :
  
  class LanceMissile:public Vaisseau

  --> 	m.test_vaisseau(); dans fonc et fonc2 refusent de fonctionner.

  En effet, un héritage protected ne récupere pas les méthodes publiques de la mere.
  Ainsi, vous ne pourrez vous servir de test_vaisseau() que dans une des méthodes de LanceMissile OU d'une de ses filles (Manta par exemple)

  Si maintenant vous mettez 
  class LanceMissile:private Vaisseau

  La, c'est pareil a une différence pres :
  Ainsi, vous ne pourrez vous servir de test_vaisseau() que dans une des méthodes de LanceMissile MAIS PAS d'une de ses filles (Manta par exemple)

  Si vous mettez private, d'autre messages d'erreur apparaissent :

  	void testheritagesecurit()
	{
		test_lancemissile();
		test_vaisseau();              <------- Ici, car on essaie, a partir de Manta, d'accéder a la classe Vaisseau, et ça n'est pas possible pour la raison vue au dessus.

	}

	void test_mantaship()
	{
		a=4;       <------- Ici, car, du a l'héritage privé, tout devient privé dans la classe mere pour cetet instance, y compris les champs protected qui deviennent privés.
		b=5;
		c=6;
		cout << "MantaShip::test_mantaship" << endl;
	}

Utilisation d'un héritage privé ou protégé :
********************************************

  Quel est l'intéret d'hériter d'une classe si ce n'est pas pour rendre publique ses méthodes ?

  Prenons un exemple :

  Vous avez une classe de liste chainée : cette classe permet, en public, d'ajouter des éléments des 2 cotés, et d'en enlever des 2 cotés.

  Vous voulez faire une classe PILE a partir de la : c'est a dire une classe ou finalement, on empile et dépile des éléments.
  Et bien, comme votre pile sera en interne, une liste chainée, vous faites hériter pile de list.
  Cependant, vous ne voulez pas qu'on puisse, dans une pile, insérer ou supprimer des éléments ou on veut.
  Donc vous coupez l'acces aux méthodes publiques de la classe mere "liste".

  --> Héritage non publique.