// c.f. : http://openclassrooms.com/courses/programmez-avec-le-langage-c/le-polymorphisme-1
#include <iostream>
#include <vector>

using namespace std;

class Vehicule {
//==============
public:
Vehicule(int prix);           //Construit un véhicule d'un certain prix
virtual void affiche() const; // Affiche une description du véhicule
virtual ~Vehicule();          //Remarquez le 'virtual' ici

protected:
int m_prix; // chaque céhicule a un prix
}; // Vehicule

class Voiture: public Vehicule {
//==============================
// Une voiture est un Vehicule
public:
Voiture(int prix, int portes); //Construit une voiture dont on fournit le prix et le nombre de portes
virtual void affiche() const;
virtual ~Voiture();  // destructeur

private:
int m_portes; // Le nombre de portes de la voiture
}; // Voiture

class Moto : public Vehicule {
//============================
// Une Moto est un Vehicule
public:
Moto(int prix, double vitesseMax);   //Construit une moto d'un prix donné et ayant une certaine vitesse maximale
virtual void affiche() const;
virtual ~Moto();  // destructeur

private:
double m_vitesse; // La vitesse maximale de la moto
}; // Moto

//##########################################################

Vehicule::Vehicule(int prix) {
//=============================
m_prix = prix;
cout << "construit un vehicule de prix : " << m_prix << endl;
}

void Vehicule::affiche() const {
//==============================
cout << "Ceci est un vehicule." << endl;
}

Vehicule::~Vehicule() {
//=====================
cout << "détruit un vehicule de prix : " << m_prix << endl;
}

//##########################################################

Voiture::Voiture(int prix, int portes):Vehicule(prix) {
//=====================================================
m_portes = portes;
cout << "construit une voiture de prix : " << m_prix << ", ayant " << m_portes << " portes" << endl;
}

void Voiture::affiche() const {
//=============================
cout << "Ceci est une voiture de prix : " << m_prix << endl;
}

Voiture::~Voiture() {
//=====================
cout << "détruit une voiture de prix : " << m_prix << ", ayant " << m_portes << " m_portes"  << endl;
}

//##########################################################

Moto::Moto(int prix, double vitesse):Vehicule(prix) {
//===================================================
m_vitesse = vitesse;
cout << "construit une moto de prix : " << m_prix << ", de vitesse : "<< m_vitesse << endl;
}

void Moto::affiche() const {
//==========================
cout << "Ceci est une moto de prix : " << m_prix << endl;
}

Moto::~Moto() {
//=============
cout << "détruit une moto de prix : " << m_prix << ", de vitesse : "<< m_vitesse  << endl;
}

//##########################################################

void presenter(Vehicule const& oV) {
//==================================
// Présente le véhicule passé en argument, par référence.
oV.affiche();
}

//##########################################################

void test01() {
//=============
Vehicule oV(10);
presenter(oV); //Affiche "Ceci est un vehicule."

Moto oM(8000, 250);
presenter(oM); //Affiche "Ceci est une moto."

Voiture oVo(25000, 4);
presenter(oVo); //Affiche "Ceci est une voiture."

cout << "Terminé ----------------------" << endl;
} // test01

void test02() {
//=============
cout << "------------------- début de test02() -----------------" << endl;
 vector<Vehicule*> listeVehicules;
listeVehicules.push_back(new Voiture(10000, 3));
listeVehicules.push_back(new Voiture(20000, 5));
listeVehicules.push_back(new Moto(3000, 212.5));

// On affiche les informations de la première voiture
listeVehicules[0]->affiche();

// On affiche les informations de la deuxième voiture
listeVehicules[1]->affiche();

// On affiche les informations de la moto
listeVehicules[2]->affiche();

for(int i=0; i<listeVehicules.size(); ++i) {
  delete listeVehicules[i];  //On libère la i-ème case mémoire allouée
  listeVehicules[i] = 0;  //On met le pointeur à 0 pour éviter les soucis
  }

cout << "Terminé ----------------------" << endl;
} // test02

int main() {
//==========
test01();
test02();
return 0;
}
