J'ai tenté d'appliquer le pattern NVI.

Voici le code, bonne lecture! :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
 
/****Character.h****/
#ifndef Character_H
#define Character_H
 
#include <ostream>
#include <string>
#include "Weapon.h"
//#include "Inventory.h"
class Character {
 
    public :
    Character() {}
    Character(std::string name, int life) : _name(name), _lifePoint(life) {
        _alive = true;
        std::cout << "Character -> \'" << _name << "\' created" << std::endl;
    }
 
         //Les wrapper publics permettant d'appeler
        //les fonctions virtuelles des classes filles
        void attack(Character* ennemy) {do_attack(ennemy);}
        void attacked(Character* attacker) {do_attacked(attacker);}
 
        Weapon* getWeapon() {return do_getWeapon();}
        void setWeapon(Weapon* weapon) {do_setWeapon(weapon);}
 
        //Comportement de base de la fonction defini par les deux
        //premieres lignes puis spécialisation appelé par do_dies()
        void dies() {
            std::cout << _name << " is dead" << std::endl;
            _alive = false;
            do_dies();
        }
 
        //Les getter/setter
        std::string getName() {return _name;}
 
        int getLifePoint() {return _lifePoint;}
        void setLifePoint(int lifePoint) {_lifePoint = lifePoint;}
 
        bool getAlive() {return _alive;}
        void setAlive(bool alive) {_alive = alive;}
 
    virtual ~Character() {
    std::cout << "Character ->\'" << _name << "\' Destroyed" << std::endl;}
 
    private :
 
        //Les méthodes abstraites sont la partie customisable de l'interface
        virtual void do_attack(Character *ennemy) = 0;
        virtual void do_attacked(Character* attacker) = 0;
 
        virtual Weapon* do_getWeapon() = 0;
        virtual void do_setWeapon(Weapon* weapon) = 0;
 
        virtual void do_dies() = 0;
 
        //Noter que meme les attributs propre a Character sont private
        //Si j'ai bien compris, cela renforce l'encapsulation et empeche
        //la classe fille de redefinir des comportements faisant partie
        //de la partie constante de l'interface.
        std::string _name;
        int _lifePoint;
        bool _alive;
};
 
class Warrior : public Character {
 
    public :
    Warrior(std::string name, int life) : Character(name, life) {
        _weapon = new Weapon();
        std::cout << "Character created" << std::endl;
    }
 
    //Si je decommente delete _weapon, j'obtiens un segfault parce que
    //l'arme Flame thrower est défruite deux fois.
    //Je ne comprends pas pourquoi
    virtual ~Warrior() {/*delete _weapon;*/}
 
    private :
        virtual void do_attack(Character *ennemy);
        virtual void do_attacked(Character *attacker);
 
        //Et on retrouve ici la specialistion de do_dies
        virtual void do_dies() {_weapon->setUsable(false);}
 
        virtual Weapon* do_getWeapon() {return _weapon;}
        virtual void do_setWeapon(Weapon* weapon) {_weapon = weapon;}
 
        Weapon *_weapon;
 
};
 
#endif
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
 
/****Character.cpp****/
#include <ostream>
#include "Character.h"
 
using namespace std;
 
void Warrior::do_attack(Character *ennemy)
{
    if (_weapon->isUsable())
        ennemy->attacked(this);
    else
        std::cout << getName() << " does not have a weapon" << endl;
}
 
void Warrior::do_attacked(Character *attacker)
{
    int lifePoint = getLifePoint();
    int damage = attacker->getWeapon()->getDamage();
    switch(damage > lifePoint){
        case true :
            damage = lifePoint;
            setLifePoint(0);
            dies();
            break;
        case false :
            setLifePoint(lifePoint - damage);
            break;
    }
    cout << getName() << " lost " << damage << " life point" << endl;
}
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
 
/****Weapon.h****/
#ifndef WEAPON_H
#define WEAPON_H
 
#include <iostream>
#include <string>
 
class Weapon {
    public :
        Weapon () : _usable(false) {}
        Weapon(std::string name, int damage) : _name(name), _damage(damage), _usable(true) {
        std::cout << "Weapon -> \'" << _name << "\' created" << std::endl;}
 
        ~Weapon(){
        std::cout << "Weapon -> \'" << _name <<"\' Destroyed" << std::endl;
        }
        int getDamage() {return _damage;}
        bool isUsable () {return _usable;}
        void setUsable(bool usable) {_usable = usable;}
 
    private:
        std::string _name;
        int _damage;
        bool _usable;
 
};
 
#endif
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
 
/*Et un petit main pour tester*/
 
#include <ostream>
 
#include "Character.h"
#include "Weapon.h"
//#include "Inventory.h"
//#include "Item.h"
 
using namespace std;
 
int main()
{
    cout << "\n\\=*=*=*=*=*=*=*=*=*Creation=*=*=*=*=*=*=*=*=*=/\n" << endl;
    Warrior a("Mike", 50);
    Warrior b("Gob", 20);
    Weapon sword("Sword", 25);
    Weapon flameThrower("Flame Thrower", 45);
 
    a.setWeapon(&sword);
    b.setWeapon(&flameThrower);
 
    cout << "\n\\=*=*=*=*=*=*=*=*=*Operation=*=*=*=*=*=*=*=*=*=/\n" << endl;
 
    a.attack(&b);
 
    cout << "\n\\=*=*=*=*=*=*=*=*Destructions=*=*=*=*=*=*=*=*=/\n" << endl;
    return 0;
}
Mes principales questions sont intégrées en commentaires dans le code.
(principalement, le destructeur de Warrior me pose problème...)

Sinon, j'attends bien évidemment des critiques (constructives!) sur mon implémentation de ce pattern et sur mon code ne général.
Ce code n'est qu'un code d'exercice, il se veut donc volontairement simplifier.

Merci d'avance à tous ceux qui vont prendre de leur précieux temps pour lire mon code et rédiger une réponse me permettant, ultimement, d'améliorer mes connaissances du C++.