Aller au menu - Aller au contenu

[Plan du site] Vous êtes ici --- > Le Site du Zéro > Les tutoriels > Officiels > Programmation > Apprenez à programmer en C++ ! > [Théorie] La Programmation Orientée Objet > Les classes (Partie 1/2) > Lecture du tutoriel

Les classes (Partie 1/2)

Avatar
Auteur : M@teo21
Note : 19 / 20 (10 votes)
Visualisations : 121 699

Plus d'informations Plus d'informations
Dans le chapitre précédent, vous avez vu que la programmation orientée objet pouvait nous simplifier la vie en "masquant" en quelque sorte le code complexe. Ca c'est un des avantages de la POO, mais ce n'est pas le seul comme vous allez le découvrir petit à petit. Par exemple, un autre gros avantage des objets est qu'ils sont facilement réutilisables et modifiables.

A partir de maintenant, nous allons apprendre à créer des objets. Vous allez voir que c'est tout un art et que ça demande de la pratique. Il y a beaucoup de programmeurs qui prétendent faire de la POO et qui le font pourtant très mal (et je ne m'exclue pas forcément du lot ;) ). En effet, on peut créer un objet de 100 façons différentes, et c'est à nous de choisir à chaque fois la meilleure, la plus adaptée. Pas évident. Il faudra donc bien réfléchir avant de se lancer dans le code comme des forcenés :p


Allez, on prend une grande inspiration, et on plonge ensemble dans l'océan de la POO ! ^^
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Créer une classe

Commençons par la question qui doit vous brûler les lèvres :p

Je croyais qu'on allait apprendre à créer des objets, pourquoi tu nous parles de créer une classe maintenant ?
Quel est le rapport ?


Eh bien justement, pour créer un objet, il faut d'abord créer une classe !
Je m'explique : pour construire une maison, vous avez besoin d'un plan d'architecte non ? Eh bien imaginez simplement que la classe c'est le plan, et que l'objet c'est la maison.

"Créer une classe", c'est donc dessiner les plans de l'objet.

Une fois que vous avez les plans, vous pouvez faire autant de maisons que vous voulez en vous basant sur les plans. Pour les objets c'est pareil : une fois que vous avez fait la classe (le plan), vous pourrez créer autant d'objets du même type que vous voulez :)

Vocabulaire : on dit qu'un objet est une instance d'une classe. C'est un mot très courant que l'on rencontre souvent en POO. Cela signifie qu'un objet est la matérialisation concrète d'une classe (tout comme la maison est la matérialisation concrète du plan de la maison).
Oui je sais c'est très métaphysique la POO, mais vous allez voir on s'y fait ^^



Créer une classe, oui mais laquelle ?



Avant tout, il va falloir choisir la classe sur laquelle nous allons travailler.

Pour reprendre mon exemple sur l'architecture : allons-nous créer un appartement, une villa avec piscine, un spacieux loft ?
En clair, quel type d'objet voulons-nous être capable de créer ?

Les choix ne manquent pas. Je sais que, quand on débute, on a du mal à imaginer ce qui peut être considéré comme un objet. La réponse est : presque tout !

Vous allez voir, vous allez petit à petit avoir le feeling qu'il faut avec la POO. Puisque vous débutez, c'est moi qui vais choisir (vous avez pas trop le choix de toute façon :p ).
Pour notre exemple, nous allons créer une classe Personnage qui va permettre de représenter un personnage de jeu de rôle (RPG).

Si vous n'avez pas l'habitude des jeux de rôle, rassurez-vous, moi non plus. Vous n'avez pas besoin de savoir jouer à des RPG pour suivre ce chapitre. J'ai choisi cet exemple car il me paraît didactique, amusant, et qu'il peut déboucher sur la création d'un jeu à la fin ;)


Bon, on la crée cette classe ?



C'est parti :)

Pour commencer, je vous rappelle qu'une classe est constituée :


(n'oubliez pas ce vocabulaire, il est fon-da-men-tal !)

Pour tout vous dire, les classes ressemblent beaucoup aux structures qu'on avait étudiées en C, sauf qu'elles contiennent en plus des méthodes (les fonctions).
Vous allez donc voir que cela ressemble pas mal aux structures, du moins au premier abord.

Voici le code minimal pour créer une classe :

Code : C++
1
2
3
4
class Personnage
{
    
}; // N'oubliez pas le point-virgule à la fin !


On utilise comme vous le voyez le mot-clé class.
Il est suivi du nom de la classe que l'on veut créer. Ici, c'est Personnage.

Souvenez-vous de cette règle très importante : il faut que le nom de vos classes commence toujours par une lettre majuscule ! Bien que ce ne soit pas obligatoire (le compilateur ne gueulera pas si vous commencez par une minuscule), cela vous sera très utile par la suite pour différencier les types de variable classiques (int, double, bool, ...) des classes (Personnage, ...).


C'est entre les accolades que nous allons écrire la définition de la classe. Tout ou presque se passera à l'intérieur de ces accolades.
Et surtout, super important, le truc qu'on oublie au moins une fois dans sa vie : il y a un point-virgule après l'accolade fermante, tout comme avec les structures !


Ajout de méthodes et d'attributs



Bon c'est bien beau, mais notre classe Personnage est plutôt... vide.
Que va-t-on mettre dans la classe ? Vous le savez déjà voyons ;)



Le but du jeu maintenant, c'est justement d'arriver à faire la liste de tout ce qu'on veut mettre dans notre Personnage. De quels attributs et de quelles méthodes a-t-il besoin ? Ca, c'est justement l'étape de réflexion, la plus importante. C'est pour ça que je vous ai dit au début de ce chapitre qu'il fallait surtout pas coder comme des barbares dès le début, mais prendre le temps de réfléchir.

Cette étape de réflexion avant le codage est essentielle quand on fait de la POO. Beaucoup de gens, dont moi, ont l'habitude de sortir une feuille de papier et un crayon pour arriver à établir la liste des attributs et méthodes dont ils vont avoir besoin.
On en reparlera plus tard, mais sachez déjà qu'un langage spécial appelé UML a été spécialement conçu pour "dessiner" les classes avant de commencer à les coder.


Par quoi commencer : les attributs ou les méthodes ? Il n'y a pas d'ordre en fait, mais je trouve un peu plus logique de commencer par voir les attributs puis les méthodes.


Les attributs



C'est ce qui va caractériser votre classe, ici le personnage. Ce sont des variables, elles peuvent donc évoluer au fil du temps. Mais qu'est-ce qui caractérise un personnage de jeu de rôle ? Allons, un petit effort ^^


On peut donc déjà commencer à compléter notre classe avec ces premiers attributs :

Code : C++
1
2
3
4
5
6
7
class Personnage
{
    int m_vie;
    int m_mana;
    string m_nomArme;
    int m_degatsArme;
};


Deux trois petites choses à savoir sur ce code :



Les méthodes



Les méthodes, elles, sont grosso modo les actions que le personnage peut faire ou qu'on peut lui faire faire. Les méthodes lisent et modifient les attributs.

Voici quelques actions qu'on peut faire avec notre personnage :


Voilà c'est un bon début je trouve :)

On va rajouter ça dans la classe avant les attributs (on préfère présenter les méthodes avant les attributs en POO, bien que ça ne soit pas obligatoire) :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Personnage
{
    // Méthodes
    void recevoirDegats(int nbDegats)
    {

    }

    void attaquer(Personnage &cible)
    {

    }

    void boirePotionDeVie(int quantitePotion)
    {

    }

    void changerArme(string nomNouvelleArme, int degatsNouvelleArme)
    {

    }

    bool estVivant()
    {

    }

    // Attributs
    int m_vie;
    int m_mana;
    string m_nomArme;
    int m_degatsArme;    
};


Je n'ai pas écrit le code des méthodes exprès, on le fera après ;)


Ceci dit, vous devriez déjà avoir une petite idée de ce que vous allez mettre dans ces méthodes.

Par exemple, recevoirDegats retranchera le nombre de dégâts indiqués en paramètre par nbDegats à la vie du personnage.
Intéressante aussi : la méthode attaquer. Elle prend en paramètre... un autre personnage, plus exactement une référence vers le personnage cible que l'on doit attaquer ! Et que fera cette méthode à votre avis ? Eh oui, elle appellera la méthode recevoirDegats de la cible pour lui infliger des dégâts :D

Vous commencez à comprendre un peu comment tout cela est lié et terriblement logique ? ^^
On met en général un peu de temps avant de "penser objet" correctement. Si vous vous dites que vous n'auriez pas pu inventer un truc comme ça tout seul, rassurez-vous, tous les débutants passent par là. A force de pratiquer, ça va venir :)

Pour info, toutes les méthodes que l'on pourrait créer ne sont pas là : par exemple, on n'utilise pas de magie (mana) ici. Le personnage attaque seulement avec une arme (une épée par exemple) et n'utilise donc pas de sorts magiques. Je laisse exprès quelques fonctions manquantes pour vous inciter à compléter la classe avec vos idées ;)

En résumé : comme je vous l'avais dit, un objet est bel et bien un mix de "variables" (les attributs) et de "fonctions" (les méthodes). La plupart du temps, les méthodes lisent et modifient les attributs de l'objet pour le faire évoluer.
Un objet est au final un petit système intelligent et autonome qui est capable de surveiller son bon fonctionnement tout seul.

Droits d'accès et encapsulation

Nous allons maintenant nous intéresser au concept le plus fondamental de la POO : l'encapsulation. Ne vous laissez pas effrayer par ce mot, vous allez vite comprendre ce que ça signifie.

Tout d'abord un petit rappel. En POO, il y a 2 parties bien distinctes :


Il faut bien distinguer ces 2 parties, car ça devient ici très important.

Je mets un exemple création / utilisation côte à côte pour que vous puissiez bien les différencier :

Création de la classeUtilisation de l'objet
Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Personnage
{
    void recevoirDegats(int nbDegats)
    {
 
    }
 
    void attaquer(Personnage &cible)
    {
 
    }
 
    void boirePotionDeVie(int quantitePotion)
    {
 
    }
 
    void changerArme(string nomNouvelleArme, int degatsNouvelleArme)
    {
 
    }
 
    bool estVivant()
    {
 
    }
 
    int m_vie;
    int m_mana;
    string m_nomArme;
    int m_degatsArme;
 
};
Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
int main()
{
    Personnage david, goliath;
 
    goliath.attaquer(david);
    david.boirePotionDeVie(20);
    goliath.attaquer(david);
    david.attaquer(goliath);
    goliath.changerArme("Double hache tranchante vénéneuse de la mort", 40);
    goliath.attaquer(david);
 
 
    return 0;
}


Tenez, pourquoi on n'essaierait pas ce code ?
Allez, on met tout dans un même fichier (en prenant soin de définir la classe avant le main), et zou !

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <string>
 
using namespace std;
 
class Personnage
{
    // Méthodes
    void recevoirDegats(int nbDegats)
    {
 
    }
 
    void attaquer(Personnage &cible)
    {
 
    }
 
    void boirePotionDeVie(int quantitePotion)
    {
 
    }
 
    void changerArme(string nomNouvelleArme, int degatsNouvelleArme)
    {
 
    }
 
    bool estVivant()
    {
 
    }
 
    // Attributs
    int m_vie;
    int m_mana;
    string m_nomArme;
    int m_degatsArme;
};
 
int main()
{
    Personnage david, goliath; // Création de 2 objets de type Personnage : david et goliath
 
    goliath.attaquer(david); // goliath attaque david
    david.boirePotionDeVie(20); // david boit une potion de vie qui lui rapporte 20 de vie
    goliath.attaquer(david); // goliath réattaque david
    david.attaquer(goliath); // david contre-attaque... c'est assez clair non ? ^^
    goliath.changerArme("Double hache tranchante vénéneuse de la mort", 40);
    goliath.attaquer(david);
 
 
    return 0;
}


Compilez et admirez... la belle erreur de compilation ?! o_O

Error : void Personnage::attaquer(Personnage&) is private within this context

Une nouvelle insulte ?
Vous allez voir, le compilateur ne manque pas d'insultes en C++, vous allez sûrement en rencontrer pas mal ^^


Les droits d'accès



On en arrive justement au problème qui nous intéresse : celui des droits d'accès (eh ouais j'ai fait exprès de provoquer cette erreur de compilation, vous aviez quand même pas cru que j'avais pas tout prévu ? :-° ).

Ouvrez grand vos oreilles : chaque attribut et chaque méthode d'une classe peut posséder son propre droit d'accès. Il existe grosso modo 2 droits d'accès différents :


Il existe d'autres droits d'accès mais ils sont un peu plus complexes. Nous les verrons plus tard.


Concrètement, qu'est-ce que ça signifie ? Qu'est-ce que "l'extérieur" de l'objet ?
Eh bien sur notre exemple, "l'extérieur" c'est le main. En effet, c'est là où on utilise l'objet. On fait appel à des méthodes, mais comme elles sont privées par défaut, on ne peut pas les appeler depuis le main !

Pour modifier les droits d'accès et mettre par exemple public, il faut taper public suivi du symbole : (deux points). Tout ce qui se trouvera à la suite sera public.

Voici ce que je vous propose de faire : on va mettre en public toutes les méthodes, et en privé tous les attributs.
Ca donne ça :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Personnage
{
    // Tout ce qui suit est public (accessible depuis l'extérieur)
    public:
    
    void recevoirDegats(int nbDegats)
    {
 
    }
 
    void attaquer(Personnage &cible)
    {
 
    }
 
    void boirePotionDeVie(int quantitePotion)
    {
 
    }
 
    void changerArme(string nomNouvelleArme, int degatsNouvelleArme)
    {
 
    }
 
    bool estVivant()
    {
 
    }
 
    // Tout ce qui suit est privé (inaccessible depuis l'extérieur)
    private:
    
    int m_vie;
    int m_mana;
    string m_nomArme;
    int m_degatsArme;
};


Tout ce qui suit le public: est public. Donc toutes nos méthodes sont publiques.
Ensuite vient le mot-clé private:. Tout ce qui suit ce mot-clé est privé. Donc tous nos attributs sont privés.

Voilà, vous pouvez maintenant compiler ce code, et vous verrez qu'il n'y a pas de problème (même si le code ne fait rien pour l'instant :p ). On appelle des méthodes depuis le main, mais comme elles sont publiques, on a le droit de le faire.
... par contre, nos attributs sont privés, ce qui veut dire qu'on n'a pas le droit de les modifier depuis le main. En clair, on ne peut pas faire depuis le main :

Code : C++
1
goliath.m_vie = 90;


Essayez, vous verrez que le compilateur vous ressort la même erreur que tout à l'heure : "ton bidule est private... bla bla bla... pas le droit d'appeler un élément private depuis l'extérieur de la classe".

Mais alors... ça veut dire qu'on ne peut pas modifier la vie du personnage depuis le main ? Eh oui !
C'est nul ? Non au contraire, c'est très bien pensé, ça s'appelle l'encapsulation ;)


L'encapsulation



Moi j'ai une solution ! Si on mettait tout en public ? Les méthodes ET les attributs en public, comme ça on peut tout modifier depuis le main et plus aucun problème !
... quoi j'ai dit une connerie ? :euh:

Oh, trois fois rien, vous venez juste de vous faire autant d'ennemis qu'il n'y a de programmeurs qui font de la POO dans le monde :lol:

Il y a une règle d'or en POO, et tout découle de là. S'il vous plaît, imprimez ceci en gros sur une feuille, et placardez cette feuille sur un mur de votre chambre :

Encapsulation : tous les attributs d'une classe
doivent toujours être privés


Ca a l'air bête, stupide, irréfléchi, et pourtant tout ce qui fait que la POO est un principe puissant vient de là.
En clair, si j'en vois un à partir de maintenant qui me met ne serait-ce qu'un seul attribut en public, je le brûle, je le torture, je l'écorche vif sur la place publique, compris ? :diable:
Et vous, si vous voyez quelqu'un d'autre faire ça un jour, écorchez-le vif en pensant à moi, vous serez sympa :-°

Voilà qui explique pourquoi j'ai fait exprès dès le début de mettre les attributs en privé. Comme ça, on ne peut pas les modifier depuis l'extérieur de la classe, et ça respecte le principe d'encapsulation.

Vous vous souvenez de ce schéma du chapitre précédent ?

Image utilisateur


Les fioles chimiques, ce sont les attributs.
Les boutons sur la façade avant, ce sont les méthodes.

Et là, pif paf pouf, vous devriez avoir tout compris d'un coup. En effet, le but du modèle objet c'est justement de masquer les informations complexes à l'utilisateur (les attributs) pour éviter qu'il ne fasse des bêtises avec.

Imaginez par exemple que l'utilisateur puisse modifier la vie... qu'est-ce qui l'empêcherait de mettre 150 de vie alors que la limite maximale est 100 ? C'est pour ça qu'il faut toujours passer par des méthodes (des fonctions) qui vont d'abord vérifier qu'on fait les choses correctement avant de modifier les attributs.
Cela permet de faire en sorte que le contenu de l'objet reste une "boîte noire". On ne sait pas comment ça fonctionne à l'intérieur quand on l'utilise, et c'est très bien. C'est une sécurité, ça permet d'éviter de faire péter tout le bazar de fioles chimiques à l'intérieur :-°

Séparer prototypes et définitions

Bon, on avance mais on n'a pas fini ^^
Voici ce que je voudrais qu'on fasse :



Pour le moment, on a mis notre classe dans le fichier main.cpp, juste au-dessus du main. Et les méthodes sont directement écrites dans la définition de la classe.
Ca fonctionne, mais c'est un peu bourrin. Tout comme on avait appris en C à faire du code modulaire, on va voir comment on procède en POO pour séparer tout ça proprement dans des fichiers différents.

Tout d'abord, il faut clairement séparer le main (qui se trouve dans main.cpp) des classes.
Pour chaque classe, on va créer :


Je vous propose d'ajouter à votre projet 2 fichiers nommés très exactement :


(vous noterez que je mets aussi une majuscule à la première lettre du nom de fichier, histoire d'être cohérent jusqu'au bout)

Vous devriez être capables de faire ça tous seuls avec votre IDE favori. Sous Code::Blocks, je fais File / New File, je rentre par exemple le nom "Personnage.h" avec l'extension, et je réponds "Oui" quand Code::Blocks me demande si je veux ajouter le nouveau fichier au projet en cours :

Ajouter un fichier au projet


Personnage.h



Le fichier .h va donc contenir la déclaration de la classe avec les attributs et les prototypes des méthodes. Dans notre cas, pour la classe Personnage, ça va donner ça :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef DEF_PERSONNAGE
#define DEF_PERSONNAGE

class Personnage
{
    public:

    void recevoirDegats(int nbDegats);
    void attaquer(Personnage &cible);
    void boirePotionDeVie(int quantitePotion);
    void changerArme(std::string nomNouvelleArme, int degatsNouvelleArme);
    bool estVivant();


    private:

    int m_vie;
    int m_mana;
    std::string m_nomArme; // Pas de using namespace std, donc il faut mettre std:: devant string.
    int m_degatsArme;
};

#endif


Comme vous pouvez le constater, seuls les prototypes des méthodes sont présents dans le .h. C'est déjà beaucoup plus clair :)

Dans les .h, il est recommandé de ne jamais mettre la directive using namespace std; car cela pourrait avoir des effets néfastes lorsque vous utiliserez la classe par la suite.
Par conséquent, il faut rajouter le préfixe "std::" devant chaque string du .h. Sinon, le compilateur vous sortira une erreur du type "string does not name a type".


Personnage.cpp



C'est là qu'on va écrire le code de nos méthodes (on dit qu'on implémente les méthodes).
Première chose à ne pas oublier, sinon ça va pas bien se passer, c'est d'inclure <string> "Personnage.h".
On peut aussi rajouter ici un using namespace std;. On a le droit de le faire car on est dans le .cpp (par contre comme je vous l'ai expliqué plus tôt, il faut éviter de le mettre dans le .h).

Code : C++
1
2
3
4
#include <string>
#include "Personnage.h"

using namespace std;


Veillez à inclure <string> AVANT Personnage.h, sinon la déclaration de la classe contenue dans Personnage.h n'aura pas connu au préalable le type string... et donc la compilation plantera.


Maintenant, voilà comment ça se passe : pour chaque méthode, vous devez faire précéder le nom de la méthode par le nom de la classe suivi de deux fois deux points "::". Pour recevoirDegats ça donne ça :

Code : C++
1
2
3
4
void Personnage::recevoirDegats(int nbDegats)
{

}


Cela permet au compilateur de savoir que cette méthode se rapporte à la classe Personnage. En effet, comme la méthode est ici écrite en dehors de la définition de la classe, le compilateur n'aurait pas su à quelle classe appartenait cette méthode.


Personnage::recevoirDegats



Maintenant, c'est parti, implémentons la méthode recevoirDegats. Je vous avais expliqué un peu plus haut ce qu'il fallait faire. Vous allez voir, c'est très simple :

Code : C++
1
2
3
4
5
6
7
8
9
void Personnage::recevoirDegats(int nbDegats)
{
    m_vie -= nbDegats; // On enlève le nombre de dégâts reçus à la vie du personnage
    
    if (m_vie < 0) // Pour éviter d'avoir une vie négative
    {
        m_vie = 0; // On met la vie à 0 (ça veut dire mort)
    }
}


La méthode modifie donc la valeur de la vie. La méthode a le droit de modifier l'attribut, car elle fait partie de la classe. Ne soyez donc pas surpris, c'est justement l'endroit où on a le droit de toucher aux attributs ;)

La vie est diminuée du nombre de dégâts reçus. En théorie, on aurait pu se contenter de la première instruction, mais on fait une vérification supplémentaire. Si la vie est descendue en-dessous de 0 (parce qu'on a reçu 20 de dégâts alors qu'on n'avait que 10 de vie), on ramène la vie à 0 afin d'éviter d'avoir une vie négative (ça fait pas très pro une vie négative :-° ). De toute façon, à 0 de vie, le personnage est considéré comme mort ^^

Et voilà pour la première méthode ! Allez on enchaîne hop hop hop !


Personnage::attaquer



Code : C++
1
2
3
4
void Personnage::attaquer(Personnage &cible)
{
    cible.recevoirDegats(m_degatsArme); // On inflige à la cible les dégâts que causent notre arme
}


Cette méthode est peut-être très courante, elle n'en est pas moins très intéressante !
On reçoit en paramètre une référence vers un objet de type Personnage. On aurait pu recevoir un pointeur aussi, mais comme les références sont plus faciles à manipuler (cf les chapitres précédents) on ne va pas s'en priver.

La référence concerne le personnage cible que l'on doit attaquer. Pour infliger des dégâts à la cible, on appelle sa méthode recevoirDegats en faisant : cible.recevoirDegats

On ne peut pas modifier directement la vie de la cible en faisant cible.m_vie car la cible est un AUTRE objet (même s'il est aussi issu de la classe Personnage). On n'a le droit d'accéder qu'aux éléments publics de cet autre objet, donc à ses méthodes.


Quelle quantité de dégâts envoyer à la cible ? Vous avez la réponse sous vos yeux : le nombre de points de dégâts indiqués par l'attribut m_degatsArme ! On envoie donc la valeur des m_degatsArme de notre personnage à la cible.

Personnage::boirePotionDeVie



Code : C++
1
2
3
4
5
6
7
8
9
void Personnage::boirePotionDeVie(int quantitePotion)
{
    m_vie += quantitePotion;

    if (m_vie > 100) // Interdiction de dépasser 100 de vie
    {
        m_vie = 100;
    }
}


Le personnage reprend autant de vie que ce que la potion qu'il boit lui permet d'en récupérer. On vérifie au passage qu'il ne dépasse pas les 100 de vie, car comme on l'a dit plus tôt, il est interdit d'avoir plus de 100 de vie.


Personnage::changerArme



Code : C++
1
2
3
4
5
void Personnage::changerArme(string nomNouvelleArme, int degatsNouvelleArme)
{
    m_nomArme = nomNouvelleArme;
    m_degatsArme = degatsNouvelleArme;
}


Pour changer d'arme, on stocke dans nos attributs le nom de la nouvelle arme ainsi que ses nouveaux dégâts. Les instructions sont très simples : on fait juste passer ce qu'on a reçu en paramètres dans nos attributs.
Grâce à l'objet string d'ailleurs, il suffit de faire un simple "=" pour affecter la chaîne, et on n'a plus à se préoccuper de la taille du tableau car l'objet string se débrouille tout seul pour ça (à chaque fois que j'y pense je trouve ça génial ^^ ).


Personnage::estVivant



Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
bool Personnage::estVivant()
{
    if (m_vie > 0) // Plus de 0 de vie ?
    {
        return true; // VRAI, il est vivant !
    }
    else
    {
        return false; // FAUX, il n'est plus vivant !
    }
}


Cette méthode permet de vérifier si le personnage est toujours vivant. Elle renvoie vrai (true) s'il a plus de 0 de vie, et faux (false) sinon.


Code complet de Personnage.cpp



En résumé, le code complet de notre Personnage.cpp est le suivant :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <string>
#include "Personnage.h"

using namespace std;

void Personnage::recevoirDegats(int nbDegats)
{
    m_vie -= nbDegats; // On enlève le nombre de dégâts reçus à la vie du personnage

    if (m_vie < 0) // Pour éviter d'avoir une vie négative
    {
        m_vie = 0; // On met la vie à 0 (ça veut dire mort)
    }
}

void Personnage::attaquer(Personnage &cible)
{
    cible.recevoirDegats(m_degatsArme); // On inflige à la cible les dégâts que causent notre arme
}

void Personnage::boirePotionDeVie(int quantitePotion)
{
    m_vie += quantitePotion;

    if (m_vie > 100) // Interdiction de dépasser 100 de vie
    {
        m_vie = 100;
    }
}

void Personnage::changerArme(string nomNouvelleArme, int degatsNouvelleArme)
{
    m_nomArme = nomNouvelleArme;
    m_degatsArme = degatsNouvelleArme;
}

bool Personnage::estVivant()
{
    if (m_vie > 0) // Plus de 0 de vie ?
    {
        return true; // VRAI, il est vivant !
    }
    else
    {
        return false; // FAUX, il n'est plus vivant !
    }
}



main.cpp



Retour au main. Première chose à ne pas oublier : inclure Personnage.h pour pouvoir créer des objets de type Personnage.

Code : C++
1
#include "Personnage.h" // Ne pas oublier


Après, le main reste le même que tout à l'heure, on n'a pas besoin de le changer. Au final, le code du main est donc très court, et le fichier main.cpp ne fait qu'utiliser les objets :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <string>
#include "Personnage.h" // Ne pas oublier

using namespace std;


int main()
{
    Personnage david, goliath; // Création de 2 objets de type Personnage : david et goliath

    goliath.attaquer(david); // goliath attaque david
    david.boirePotionDeVie(20); // david boit une potion de vie qui lui rapporte 20 de vie
    goliath.attaquer(david); // goliath réattaque david
    david.attaquer(goliath); // david contre-attaque... c'est assez clair non ? ^^
    goliath.changerArme("Double hache tranchante vénéneuse de la mort", 40);
    goliath.attaquer(david);


    return 0;
}


N'exécutez pas le programme pour le moment. En effet, nous n'avons toujours pas vu comment faire pour initialiser les attributs, ce qui fait que notre programme n'est pas encore utilisable.
Nous verrons comment le rendre pleinement fonctionnel dans le chapitre suivant, et vous pourrez alors (enfin) l'exécuter ;)


Il faudra donc pour le moment vous contenter de votre imagination. Essayez d'imaginer que David et Goliath sont bien en train de combattre ! (et je veux pas faire mon gros spoiler, mais normalement c'est David qui gagne à la fin :-° ).

Q.C.M.

Quel est le rapport entre un objet et une classe ?
Quand un membre d'une classe est dans une section private, cela signifie :
Dans quel ordre doit-on placer les attributs et les méthodes dans une classe ?
Que dit la règle de l'encapsulation ?
Si je sépare la déclaration de la classe de l'implémentation des méthodes, quel préfixe dois-je mettre devant le nom des méthodes ?
Quand je fais dans le main :
Code : C++
1
Personnage david;

Qui est l'objet, et qui est la classe ?

Statistiques de réponses au QCM


Là, on peut dire qu'on est rentré en plein dans la POO ^^
Pourtant, ce n'est encore qu'un début ! De nombreuses nouvelles choses complètement dingues vous attendent dans les chapitres qui suivent (et elles vont vous rendre dingues ça c'est sûr :-° )

Un conseil si je puis me permettre : assurez-vous d'avoir bien compris qu'il y avait deux faces dans la POO, la création de la classe, et l'utilisation des objets. Il faut être à l'aise avec ce concept.
Mais tout n'est pas si simple. Comme vous le verrez, ce que font les objets la plupart du temps c'est... utiliser d'autres objets ! Et c'est en combinant plusieurs objets entre eux que l'on découvrira le vrai pouvoir de la POO ;)
Chapitre précédent Sommaire Chapitre suivant
Retour en haut Retour en haut


Créé : le 18/09/2007 à 17:13:58
Modifié : le 23/10/2008 à 14:17:50
Avancement : 100%
Licence : Copie non autorisée

Changer de design | En savoir plus | Plan du site | Politique d'accessibilité | Règles | RSS tutoriels | RSS news
Édité par Simple IT SARL : Nous contacter | Notre blog | Revue de presse | Publicité

Y'a plus rien à lire, faut remonter maintenant !

Hébergement web - Correction de tutoriels - Créer un site
Vous souhaitez apparaître ici ? Contactez-nous.

Nombre de connectés 207 Zéros connectés | Requêtes SQL 9 requêtes | Temps de génération de la page : Total (SQL) 0.3097s (0.2932s)