Bonjour
le programme suivant marche mais l'encapsulation est brisée .


implementation.h
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
 
#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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : 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
#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 : 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
#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 : 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
#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.