probleme d'effet de bord et respect encapsulation
Bonjour
le programme suivant marche mais l'encapsulation est brisée .
implementation.h
Code:
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
|
#pragma once
#include <iostream>
#include <string>
class chargeur_m16
{
int nb_de_balle;
static int nb_de_chargeur;
public:
bool balle_amene_dans_chargeur();
int nb_de_balle_restante()const;
const static int cb_de_chargeur();
bool videQ()const;
chargeur_m16();
~chargeur_m16();
};
class M_16
{
int x,y,z;
enum type_cadence_de_tir{un_coup,rafale}cadence_de_tir;
bool balle_amorce;
static int nb_de_coup_tire;
int f();
public:
chargeur_m16 *pt;//encapsulation cassée
bool amorcer_la_balle();
int tirer();
void changer_cadence_de_tir();
void etat_selecteur_cadence_de_tir()const;
chargeur_m16* emplacement_du_chargeur();
static void cb_de_coup_tire();
void changer_chargeur(int numero);
M_16(int a,int b,int c);
~M_16();
};
class soldier
{
int sante;
int x,y,z;
std::string nom;
M_16 *pt;//1 seul arme
chargeur_m16* sac[10];
//enum type_grade{PRIVATE,CORPORAL,SERGEANT,LIEUTENANT,CAPTAIN,MAJOR,LIEUTENANT_COLONEL,COLONEL}grade;
public:
soldier(int a,int b ,int c,std::string n);
~soldier();
void changer_chargeur(int numero);
M_16& utiliser_arme();
M_16& soldier::utiliser_arme_pt(soldier &cible,chargeur_m16 *t);//test
M_16& utiliser_arme(soldier& cible);
bool vie()const;
void damage(int a);
std::string get_nom()const;
}; |
chargeur_m16.cpp
Code:
1 2 3 4 5 6 7 8 9 10
| #include "implementation.h"
int chargeur_m16::nb_de_chargeur=0;
chargeur_m16::chargeur_m16():nb_de_balle(30){nb_de_chargeur++;}
chargeur_m16::~chargeur_m16(){nb_de_chargeur--;}
bool chargeur_m16::balle_amene_dans_chargeur(){if(nb_de_balle){nb_de_balle--;return true;}else{return false;}}
int chargeur_m16::nb_de_balle_restante()const{std::cout << "il reste " << nb_de_balle << " balle(s)"<< std::endl;return nb_de_balle; }
const int chargeur_m16::cb_de_chargeur(){return nb_de_chargeur;}
bool chargeur_m16::videQ()const{if(nb_de_balle)return true;else return false;} |
M_16.cpp
Code:
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
| #pragma once
#include <iostream>
#include "implementation.h"
int M_16::nb_de_coup_tire=0;
int M_16::tirer()
{
int damage=0;
if(cadence_de_tir==un_coup)
damage=f();
else
for(int i=0;i<3;i++){damage+=f();}
return damage;
}
bool M_16::amorcer_la_balle()
{
if(pt->balle_amene_dans_chargeur()){balle_amorce=true;return true;}
else{std::cout << "impossible d'amorce une balle(chargeur vide?) "<< std::endl;return false;}
}
int M_16::f()
{
if(balle_amorce){std::cout << "pan" << std::endl;balle_amorce=amorcer_la_balle();nb_de_coup_tire++;return 40;}
else {std::cout << "click (balle non amorce)" << std::endl; return 0;}
}
void M_16::etat_selecteur_cadence_de_tir()const
{
if(cadence_de_tir==rafale)std::cout << "mode rafale" << std::endl;
else std::cout << "mode un coup" << std::endl;
}
void M_16::changer_cadence_de_tir()
{
if(cadence_de_tir==rafale)cadence_de_tir=un_coup;
else cadence_de_tir=rafale;
}
M_16::M_16(int a,int b,int c):cadence_de_tir(un_coup),balle_amorce(false),x(a),y(b),z(c){pt=new chargeur_m16;}
M_16::~M_16(){delete pt; }
chargeur_m16* M_16::emplacement_du_chargeur(){return pt;}
void M_16::cb_de_coup_tire()
{
std::cout << "l'arme a tire " << nb_de_coup_tire << " coup"<< std::endl;
} |
soldier.cpp
Code:
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
| #pragma once
#include "implementation.h"
soldier::soldier(int a,int b ,int c,std::string n):sante(100),x(a),y(b),z(c),nom(n)
{
pt=new M_16(x,y,z);
for(int i=0;i<10;i++){sac[i]=new chargeur_m16; }
}
soldier::~soldier()
{
for(int i=0;i<10;i++){delete sac[i]; }
delete pt;
}
bool soldier::vie()const
{
if(sante==0)
{
return false;
}
else
{
return true;
}
}
void soldier::damage(int a)
{
sante =- a;
if(sante<0)sante=0;
if (vie()==false){std::cout <<"vous avez tue "<< get_nom()<< std::endl;}
}
std::string soldier::get_nom()const{return nom;}
M_16& soldier::utiliser_arme(){if(vie())return *pt;else {std::cout << "vous etes mort" << std::endl; return *pt;}}
M_16& soldier::utiliser_arme(soldier &cible)
{
if(cible.vie())cible.damage(pt->tirer());
else std::cout << "cible deja bute" << std::endl;
return *pt;
}
M_16& soldier::utiliser_arme_pt(soldier &cible,chargeur_m16 *t)//test
{
if(cible.vie())cible.damage(pt->tirer());
else std::cout << "cible deja bute" << std::endl;
return *pt;
}
void soldier::changer_chargeur(int numero)
{
if(sac[numero])
{
chargeur_m16 *temp=pt->pt;// encapsulation cassée
pt->pt=sac[numero];
sac[numero]=temp;
}
else std::cout << "emplacement vide " << std::endl;
} |
main.cpp
Code:
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
| #pragma once
#include "implementation.h"
int main()
{
soldier ford(4,5,4,"Ford");
soldier gogol(8,9,6,"gogol");
ford.utiliser_arme().amorcer_la_balle();
ford.utiliser_arme().etat_selecteur_cadence_de_tir();
ford.utiliser_arme().changer_cadence_de_tir();
ford.utiliser_arme().etat_selecteur_cadence_de_tir();
ford.utiliser_arme(gogol);
ford.utiliser_arme(gogol);
for(int i=0;i<10;i++){ford.utiliser_arme().tirer();}
ford.utiliser_arme().cb_de_coup_tire();
ford.utiliser_arme().emplacement_du_chargeur()->nb_de_balle_restante();
ford.changer_chargeur(0);
ford.utiliser_arme().amorcer_la_balle();
for(int i=0;i<10;i++){ford.utiliser_arme().tirer();}
ford.utiliser_arme().emplacement_du_chargeur()->nb_de_balle_restante();
ford.changer_chargeur(0);
ford.utiliser_arme().amorcer_la_balle();
ford.utiliser_arme().tirer();
system("pause");
} |
j'ai essaye de rendre M_16::chargeur_m16 *pt; privé mais en utilisant des fonction qui renvoi un pointeur en argument de "changer_chargeur()" je n'ai pas d'effet de bord en dehors de la fonction du coup le programme bug avec une fuite de memoire et aussi avec 2 appel du destructeur sur un meme emplacement de memoire ...
avec un friend ca ne compile pas car soldier n'est pas encore definit
est t il possible de definir class soldier avant M_16 pour utiliser friend? le probleme est de trouve un autre moyen d'implementer void soldier::changer_chargeur(int numero); en respectant l'encapsulation soit en la mettant amie je n'y arrive pas ou en utilisant une fonction qui renvoie M_16::*pt;
merci.