• 10 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 10/02/2022

Associez des classes entre elles

La programmation orientée objet devient vraiment intéressante lorsqu'on se met à combiner plusieurs objets entre eux. Pour l'instant, nous n'avons créé qu'une seule classe : Personnage  . Or en pratique, un programme objet est un programme constitué d'une multitude d'objets différents !

Il n'y a pas de secret, c'est en pratiquant que l'on apprend petit à petit à penser objet. Ce que nous allons voir par la suite ne sera pas nouveau : vous allez réutiliser tout ce que vous savez déjà sur la création de classes, de manière à améliorer notre petit RPG et à vous entraîner à manipuler encore plus d'objets.

Créez la classe Arme

Je vous propose dans un premier temps de créer une nouvelle classe Arme  . Plutôt que de mettre les informations de l'arme ( m_nomArme  , m_degatsArme  ) directement dans Personnage  , nous allons l'équiper d'un objet de type Arme  . Le découpage de notre programme sera alors un peu plus dans la logique d'un programme orienté objet.

Qui dit nouvelle classe dit deux nouveaux fichiers :

  1. Arme.hpp  : ce fichier contient la définition de la classe.

  2. Arme.cpp  : ce fichier contient l'implémentation des méthodes de la classe.

Créez le fichier  Arme.hpp

Voici ce que je propose de mettre dans Arme.hpp  :

#ifndef DEF_ARME
#define DEF_ARME

#include <iostream>
#include <string>
 
class Arme
{
    public:
 
    Arme();
    Arme(std::string nom, int degats);
    void changer(std::string nom, int degats);
    void afficher() const;
 
    private:
 
    std::string m_nom;
    int m_degats;
};
 
#endif

Mis à part les include qu'il ne faut pas oublier, le reste de la classe est très simple.

On met le nom de l'arme et ses dégâts dans des attributs et, comme ce sont des attributs, on vérifie qu'ils sont bien privés (pensez à l'encapsulation).

Au lieu de m_nomArme et m_degatsArme  , j'ai choisi de nommer mes attributs m_nom et m_degats car on est déjà dans la classe Arme (ce n'est pas la peine de préciser dans les attributs qu'il s'agit de l'arme, on le sait).

Ensuite, on ajoute un ou deux constructeurs, une méthode pour changer d'arme à tout moment, et une autre (allez, soyons fous) pour afficher le contenu de l'arme. Reste à implémenter toutes ces méthodes dans Arme.cpp. Mais c'est facile, vous savez déjà le faire.

Créez le fichier  Arme.cpp

Entraînez-vous à écrire Arme.cpp  , c'est tout bête, les méthodes font au maximum deux lignes.

Voici mon Arme.cpp pour comparer :

#include "Arme.hpp"
 
using namespace std;
 
Arme::Arme() : m_nom("Epee rouillee"), m_degats(10)
{
 
}
 
Arme::Arme(string nom, int degats) : m_nom(nom), m_degats(degats)
{
 
}
 
void Arme::changer(string nom, int degats)
{
    m_nom = nom;
    m_degats = degats;
}
 
void Arme::afficher() const
{
    cout << "Arme : " << m_nom << " (Degats : " << m_degats << ")" << endl;
}

Et ensuite ?

Notre classe Arme est créée. Maintenant, il faut adapter la classe Personnage pour qu'elle utilise non pas m_nomArme et m_degatsArme  , mais un objet de type Arme  . Et là… les choses se compliquent.

Adaptez la classe Personnage pour utiliser la classe Arme

La classe  Personnage  va subir quelques modifications pour utiliser la  classeArme. Nous allons voir ces modifications dans la vidéo suivante. Restez attentif, car utiliser un objet dans un objet, c'est un peu particulier :

Affichez l'état de vos personnages

Nos personnages combattent dans le main(), mais… nous ne voyons rien de ce qui se passe. Il serait bien d'afficher l'état de chacun des personnages pour savoir où ils en sont.

Je vous propose de créer une méthode afficherEtat dans Personnage  . Cette méthode sera chargée de faire des cout pour afficher dans la console la vie, le mana et l'arme du personnage.

Étape 1 : Rajoutez le prototype et include

On rajoute le prototype dans le .hpp  :

void afficherEtat() const;

Étape 2 : Implémentez la méthode

 On implémente ensuite la méthode avec des cout  . Grâce aux attributs, on peut faire apparaître toutes les informations relatives au personnage :

void Personnage::afficherEtat() const
{
    cout << "Vie : " << m_vie << endl;
    cout << "Mana : " << m_mana << endl;
    m_arme.afficher();
}

Les informations sur l'arme sont demandées à l'objet m_arme via sa méthode afficher()  . Encore une fois, les objets communiquent entre eux pour récupérer les informations dont ils ont besoin.

Étape 3 : Appelez afficherEtat dans le main()

Bien, tout cela c'est bien beau mais, tant qu'on n'appelle pas la méthode, elle ne sert à rien.
Je vous propose donc de compléter le main() et de rajouter à la fin les appels de méthode :

int main()
{
    //Création des personnages
    Personnage david, goliath("Epee aiguisee", 20);
 
    //Au combat !
    goliath.attaquer(david);
    david.boirePotionDeVie(20);
    goliath.attaquer(david);
    david.attaquer(goliath);
    goliath.changerArme("Double hache tranchante veneneuse de la mort", 40);
    goliath.attaquer(david);
 
    //Temps mort ! Voyons voir la vie de chacun…
    cout << "David" << endl;
    david.afficherEtat();
    cout << endl << "Goliath" << endl;
    goliath.afficherEtat();
 
    return 0;
}

On peut enfin exécuter le programme et voir quelque chose dans la console !

David
Vie : 40
Mana : 100
Arme : Epee rouillee (Degats : 10)
 
Goliath
Vie : 90
Mana : 100
Arme : Double hache tranchante veneneuse de la mort (Degats : 40)

À vous de jouer !

Votre mission :

  1. Continuer à faire combattre david  et goliath  dans le main()  en affichant leur état de temps en temps.

  2. Introduire un troisième personnage dans l'arène pour rendre le combat plus intéressant.

  3. Rajouter un attribut m_nom  pour stocker le nom du personnage dans l'objet. Pour le moment, nos personnages ne savent même pas comment ils s'appellent, c'est un peu bête.

Je pense qu'il faudrait modifier les constructeurs et obliger l'utilisateur à indiquer un nom pour le personnage lors de sa création… à moins que vous ne donniez un nom par défaut si rien n'est précisé ? À vous de choisir !

  • Rajoutez des cout dans les autres méthodes de Personnage pour indiquer à chaque fois ce qui est en train de se passer ("Machin boit une potion qui lui redonne 20 points de vie").

  • Rajoutez d'autres méthodes au gré de votre imagination… et pourquoi pas des attaques magiques qui utilisent du mana ?

  • Enfin, pour l'instant, le combat est écrit dans le main()  , mais vous pourriez laisser le joueur choisir les attaques dans la console à l'aide de cin  .

Si vous commencez à voir des objets partout, c'est bon signe ! C'est ce que l'on appelle "penser objet".

En résumé

  • Puisque le principe d'encapsulation impose de protéger les attributs, on crée des méthodes très simples qui renvoient la valeur d'un attribut. Par exemple,getDegats() renvoie la valeur de l'attribut degats  .

  • Un objet peut contenir un autre objet au sein de ses attributs.

  • La programmation orientée objet impose un code très structuré. C'est ce qui rend le code souple, pérenne et réutilisable.

Ce n’est peut-être pas encore évident pour vous, mais pas d’inquiétude, bientôt vous verrez des objets partout. En attendant, voici un quiz pour évaluer votre niveau de compréhension. Allez c’est parti !

Exemple de certificat de réussite
Exemple de certificat de réussite