Choisissez votre style : colorisé, impression

Série 20 :
Héritage

Buts

Cette série a pour but principal de vous faire faire pratiquer la notion d'héritage. 

Préliminaires :

Avant de commencer les exercices décrits dans cette série, créez le répertoire ~/Desktop/myfiles/Programmation/cpp/serie20 et travaillez dans ce répertoire pour les exercices ne faisant pas partie du projet.
Si vous n'avez pas le temps de faire la partie "exercices" de la série, veillez au moins à en consulter le corrigé. Ceci vous donnera de précieuses indications pour le codage de votre projet.


Exercice 0 : reprise de l'exemple du cours (Héritage, niveau 0)

Pages 136 et suivantes de l'ouvrage C++ par la pratique.
Le but de cet exercice est de reprendre l'exemple du cours illustrant le concept d'héritage en utilisant une hiérarchie de figures géométriques.

Cliquez ici si vous souhaitez faire cet exercice.


Exercice 1 : Véhicules (niveau 1)

Exercice n°55 (pages 140 et 317) de l'ouvrage C++ par la pratique.

1.1 La classe Vehicule

Dans un fichier Vehicule.cc, définissez une classe Vehicule qui a pour attributs des informations valables pour tout type de véhicule: Définissez un constructeur prenant en paramètre les trois attributs correspondant à : la marque, la date d'achat et le prix d'achat (le prix courant sera calculé plus tard).

Définissez une méthode publique void affiche(ostream&) const; qui affiche l'état de l'instance, i.e. la valeur de ses attributs. , et surchargez l'operateur externe ostream& operator<<(ostream&, const Vehicule&).

1.2 La classe Voiture et la classe Avion

Définissez deux classes Voiture et Avion, héritant de la classe Vehicule et ayant les attributs supplémentaires suivants : Définissez, pour chacune de ces classes, un constructeur qui permette l'initialisation explicite de l'ensemble des attributs, ainsi que méthode affichant la valeur des attributs. Constructeurs et méthode d'affichage devront utiliser les méthodes appropriées de la classe parente !

Encore des méthodes

Ajoutez une méthode void calculePrix() dans la classe Vehicule qui à ce niveau fixe le prix courant au prix d'achat moins 1% par année entre la date d'achat et la date actuelle (1 % d'amortissement).
Utilisez le littéral 2022 pour l'année courante.

Redéfinissez cette méthode dans les deux sous-classes Voiture et Avion, afin de pouvoir calculer le prix courant en fonction de certains critères, et mettre à jour l'attribut correspondant au prix courant :

Le prix doit rester positif (i.e. s'il est négatif, on le met à 0).

Le main

Afin de tester les méthodes implémentées ci-dessus, complétez le main comme suit :
int main()
{
    vector<voiture> garage;
    vector<avion>   hangar;

    garage.push_back(Voiture("Peugeot", 1998, 147325.79, 2.5, 5, 180.0, 12000));
    garage.push_back(Voiture("Porsche", 1985, 250000.00, 6.5, 2, 280.0, 81320));
    garage.push_back(Voiture("Fiat",    2001,   7327.30, 1.6, 3,  65.0,  3000));

    hangar.push_back(Avion("Sesna",      1972, 1230673.90, HELICES,   250));
    hangar.push_back(Avion("Nain Connu", 1992, 4321098.00, REACTION, 1300));

    for (unsigned int i(0); i < garage.size(); i++)
    {
        garage[i].calculePrix();
        garage[i].affiche(cout);
    }

    for (unsigned int i(0); i < hangar.size(); i++)
    {
        hangar[i].calculePrix();
        hangar[i].affiche(cout);
    }

    return 0;

}

Exemple d'exécution :

---- Voiture ----
marque : Peugeot, date d'achat : 1998, prix d'achat : 147326, prix actuel : 88395.5
2.5 litres, 5 portes, 180 CV, 12000 km.
 ---- Voiture ----
marque : Porsche, date d'achat : 1985, prix d'achat : 250000, prix actuel : 48350
6.5 litres, 2 portes, 280 CV, 81320 km.
 ---- Voiture ----
marque : Fiat, date d'achat : 2001, prix d'achat : 7327.3, prix actuel : 4433.02
1.6 litres, 3 portes, 65 CV, 3000 km.
 ---- Avion à hélices ----
marque : Cessna, date d'achat : 1972, prix d'achat : 1.23067e+06, prix actuel : 923005
250 heures de vol.
 ---- Avion à réaction ----
marque : Nain Connu, date d'achat : 1992, prix d'achat : 4.3211e+06, prix actuel : 3.75936e+06
1300 heures de vol.


Exercice 2 : Vaccins (niveau 1)

Une compagnie pharmaceutique souhaite connaître les coûts de fabrication des vaccins qu'elle produit.

Ouvrez un fichier vaccin.cc et copiez-y le code suivant (qu'il s'agira de compléter) :

#include <string>
#include <vector>
#include <iostream>

using namespace std;

// prix du conditionnement d'une unité
const double COND_UNITE(0.5);

// prix de base de fabrication d'une unité
const double PRIX_BASE(1.5);

// majoration du prix de fabrication pour vaccin "high tech"
const double MAJORATION_HIGHTECH(0.5);

// reduction du cout du à la delocalisation
const double REDUCTION_DELOC(0.2);

enum Fabrication {Standard, HighTech};

// CLASSES A COMPLETER ICI

// ======================================================================
// 
int main() {
	

	Vaccin v1("Zamiflu", 0.55, 200000, HighTech);
	Vaccin v2("Triphas", 0.20 , 10000);
	

    // affichage des vaccins à compléter ici
	cout << v1 << endl;
	cout << v2 << endl;

	cout << "le  cout de production de  v1 et v2 est : ";
	cout << v1.cout_production() + v2.cout_production() << endl;
	
    // Test des parties suivantes
     cout << "test des parties suivantes ..." << endl;
	// A COMPLETER
  return 0;
}

Codez dans le fichier vaccins.cc la classe Vaccin dotée des attributs protégés suivants : son nom, le volume par dose (un double), le nombre de doses à produire (un int) et le mode de fabrication (qui peut être standard ou high tech, le type à donner est décrit plus bas).

Dotez votre classe Vaccin des méthodes publiques suivantes :

  1. un constructeur dont les paramètres permettent d'initialiser l'ensemble des attributs. L'attribut mode de fabrication aura Standard comme valeur par défaut (voir le type énuméré Fabrication fourni en début de fichier);
  2. une méthode d'affichage permettant d'afficher un vaccin selon le format suivant :
    Triphas
    volume/dose : 0.2
    nombre de doses: 10000
    mode de fabrication standard
    
    ou
    Zamiflu
    volume/dose : 0.55
    nombre de doses: 200000
    mode de fabrication haute technologie
    
  3. une méthode conditionnement calculant le coût de conditionnement comme étant le volume par dose multiplié par le nombre de doses à produire, multiplié par COND_UNITE (une constante fournie en début de programme);
  4. une méthode fabrication calculant le coût de fabrication d'un vaccin. Le coût de base pour la fabrication est le volume par dose multiplié par le nombre de doses à produire, multiplié par PRIX_BASE (une constante fournie en début de programme). Si le mode de fabrication est HighTech, ce coût est majoré d'un pourcentage MAJORATION_HIGHTECH (c'est à dire coût += coût * MAJORATION_HIGHTECH) où MAJORATION_HIGHTECH est aussi une constante fournie;
  5. une méthode production calculant le coût de production d'un vaccin comme étant la somme des coûts de conditionnement et de fabrication.
Pour tester votre programme, utilisez le main fourni. Vous pouvez modifier ce programme pour réaliser ces affichages en fonction de ce que vous avez déjà codé. L'exécution de votre programme devrait produire un affichage tel que:
Zamiflu
volume/dose : 0.55
nombre de doses: 200000
mode de fabrication haute technologie

Triphas
volume/dose : 0.2
nombre de doses: 10000
mode de fabrication standard

le  cout de production de  v1 et v2 est : 306500
test des parties suivantes ...
Note : Attention à ne pas utiliser de variable locale nommée cout (pour coût), car confusion avec le flot de sortie standard.

Héritage

Notre compagnie a décidé de délocaliser la fabrication de certains vaccins.

Codez une sous-classe Delocalise de Vaccin ayant pour attribut supplémentaire un booléen indiquant si la production est délocalisée dans un pays frontalier ou non.

Dotez votre nouvelle classe des méthodes suivantes :

  1. un constructeur approprié
  2. une méthode production masquant, sans duplication de code, la méthode héritée de Vaccin. Soit c le coût de production tel que calculé dans la classe Vaccin. Le coût de production d'un vaccin délocalisé vaudra :
    • c - c * REDUC_DELOC si le vaccin est délocalisé dans un pays frontalier,
    • c/2 sinon.

Pour tester votre programme, ajoutez dans le main, après le commentaire:

    // Test des parties suivantes
des instructions permettant de créer les deux vaccins Delocalise suivants :
  1. ("Zamiflu", 0.55, 15000, HighTech) et délocalisé dans un pays qui n'est pas frontalier (stocké dans une variable v3);
  2. ("Triphas", 0.20, 15000, Standard) et délocalisé dans un pays frontalier (stocké dans une variable v4).
faite afficher la somme du coût de production de ces deux vaccins. Vous devriez obtenir un affichage tel que :
le  cout de production de  v3 et v4 est : 16143.8


Exercice 3 : Héritage d'un vector (niveau 2)

Programmez un classe PorteMonnaie permettant de stocker votre argent de poche.

Un PorteMonnaie ne sera rien d'autre qu'une collection de pièces (chaque pièce est un entier).

Première façon de procéder : on dote la classe PorteMonnaie d'un attribut représentant la collection (de type vector<int>).

Seconde façon: on ne met pas d'attribut pour la collection mais on fait hériter la classe PorteMonnaie de vector <int>.

C'est cette seconde option que l'on vous demande d'implémenter ici.

PorteMonnaie héritera de façon privée de vector <int>.

Vous doterez votre classe des méthodes publiques suivantes :

  • gagner(int) ajoutant une pièce (un int) au porte-monnaie
  • vider permettant de vider le porte-monnaie de son contenu
  • ... et de tout autre méthode qui vous semblera utile.
  • Vous doterez votre classe d'une méthode d'affichage (sous la forme d' une surcharge d'opérateur) permettant d'afficher le contenu du porte-monnaie (la somme des pièces contenues dans le porte-monnaie).

    Pour coderez cette surcharge sans la déclarer friend de la classe.

    Votre programme doit pouvoir être testé avec le programme principal suivant :

    int main()
    {
    	PorteMonnaie p;
    	p.gagner(2);
    	p.gagner(3);
    	p.gagner(12);
    
    	cout << p << endl;
    
    	p.vider();
    
    	cout << p << endl;
    	
    
    	return 0;
    }
    

    l'affichage produit par ce programme sera quelque chose comme :

    Mon porte monnaie contient : 17 francs
    
    Mon porte monnaie contient : 0 francs
    
    

    Exercice 4 : attribut statique (niveau 1)

    Ouvrez le fichier ami.cc et copiez-y le code suivant :

    #include <string>
    #include <iostream>
    using namespace std;
    
    // code à compléter ici
    
    int main(){
      Ami a1("Toto", "Lausanne");
      a1.afficher();
      Ami a2(a1);
      a2.setVille("Brazzaville");
      a2.afficher();
      return 0;
    }
    
    Vous allez compléter dans ce fichier un petit programme orienté objet permettant de "gérer" un agenda. Vous souhaitez consigner dans cet agenda l'ensemble de vos amis. Un ami, représenté par une classe Ami, sera caractérisé par :

    Les contraintes suivantes seront respectées :

    1. les attributs de votre classe devront être privés. Vous ne doterez votre classes que des "getters" et "setters" éventuellement utiles au programme principal,
    2. vos constructeurs/destructeurs devront afficher des messages informatifs: "Un nouvel ami" pour la construction, "Clone d'un ami" pour la construction de copie et "Sniff, fin d'une amitié" pour la destruction,
    A l'exécution de votre programme vous devriez voir se produire quelque chose comme :
    Un nouvel ami 
    Mon ami s'appelle Toto
    Il habite Lausanne
    Clone d'un ami 
    Mon ami s'appelle Toto
    Il habite Brazzaville
    Sniff, fin d'une amitié
    Sniff, fin d'une amitié
    

    Vous souhaitez maintenant que votre classe vous permette de connaître à tout moment le nombre de vos amis habitant Lausanne (l'attribut ville vaut la chaîne de caractère "Lausanne").

    1. Dotez votre classe Ami d'un compteur statique d'amis habitant lausanne: nombre_ami_Lausanne;
    2. Mettez à jour vos constructeurs/destructeurs et toute méthode impliquée de sorte à ce que le comptage se fasse correctement;
    3. Initialisez ce compteur de façon appropriée.
    Vous ajouterez ensuite à la fin du programme principal (juste avant le return 0;) la ligne de code suivante:
     cout << "J'ai " << Ami::nombre_ami_Lausanne << " ami(s) vivant à Lausanne" << endl;
    
    L'exécution devrait alors être:
    Un nouvel ami :
    Mon ami s'appelle Toto
    Il habite Lausanne
    Clone d'un ami :
    Mon ami s'appelle Toto
    Il habite Brazzaville
    J'ai 1 ami(s) vivant à Lausanne
    Sniff, fin d'une amitié
    Sniff, fin d'une amitié
    

    Projet : continuation

    Cette semaine, vous devez commencer l'étape 2 du projet.


    Dernière mise à jour : 2024/03/21 12:12