Précédent   Forum du club des développeurs et IT Pro > C et C++ > C++ > Débuter
Débuter Forum d'entraide pour débuter en langage de programmation C++. Avant de poster : cours d'initiation au C++
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 21/11/2012, 00h23   #1
mulfycrowh
Invité régulier
 
Inscription : janvier 2006
Messages : 155
Détails du profil
Informations forums :
Inscription : janvier 2006
Messages : 155
Points : 8
Points : 8
Par défaut Mémorisation d'un pointeur

Bonjour,

J'ai cinq classes A, B, C, D et Z.
Dans ma classe Z qui est une classe contenant des symboles, les instances sont soient de type A, B, C ou D.
Je souhaiterais savoir pour chaque instance de Z vers quelle instance de A, B, C ou D elle pointe.
J'imagine donc un pointeur générique qui pourrait mémoriser un pointeur vers A ou B ou C ou D.
La taille des pointeurs vers A, B, C, D n'est pas la même car les classes sont totalement différentes.
On pourrait imaginer écrire dans le constructeur de Z :

type_symbole = "type_A";
pointeur_vers_classe = new A(...); // constructeur de A

Mais je ne vois pas comment déclarer pointeur_vers_classe.
Merci pour votre aide
mulfycrowh est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/11/2012, 02h09   #2
koala01
Modérateur
 
Avatar de koala01
 
Philippe Dunski
Inscription : octobre 2004
Messages : 8 612
Détails du profil
Informations personnelles :
Nom : Philippe Dunski
Âge : 41

Informations forums :
Inscription : octobre 2004
Messages : 8 612
Points : 13 287
Points : 13 287
Envoyer un message via MSN à koala01 Envoyer un message via Skype™ à koala01
Salut,

Le plus facile pour y arriver, c'est que A,B,C et D fassent partie d'une même hiérarchie de classe (par exemple, que B, C et D héritent toutes les trois de A).

Il "suffit" alors d'utiliser un pointeur sur la classe de base, et tu pourra, la substitution aidant, y placer un pointeur sur n'importe quel objet dérivé de la classe de base.
Cela pourrait ressembler à quelque chose comme
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class A
{ 
    /* ...*/
};
class B : public A
{ 
    /* ...*/
};
class C : public A
{ 
    /* ...*/
};
 
class D : public A
{ 
    /* ...*/
};
class Z
{
 
    private:
        A * ptr_;
};
Mais encore faut il que cela ait un sens !!!

J'ai, en effet, du mal à imaginer que l'on puisse trouver un point commun "utile et justifié" entre un oiseau, une tronçonneuse, une voiture et une fleur


Dans ce cas, il faut utiliser le principe du "type ereasure", et il est sans doute bon de te tourner vers boost::variant (si tes classes on sémantique d'entité) ou vers boost::any, si elles ont sémantique de valeur

Comme tu envisages l'utilisation d'un pointeur, tu devrais plutôt te tourner vers boost::variant, mais, ceci dit, il est peut etre utile de réfléchir à la relation réelle qui existe entre Z et les autres classes.

En effet, si la relation est "simplement" de se dire que Z "fait référence" à un objet qui peut exister de manière indépendante, le pointeur semble en effet être la meilleure solution, et le choix se tournera "naturellement" sur boost::variant .

Par contre, si Z utilise "une variable" d'un des autres type, en fonction d'un contexte quelconque et que la dite variable ne peut exister sans qu'il y ait un Z pour s'en occuper, on peut parfaitement envisager le fait de ne pas travailler avec un pointeur, mais carrément avec un objet.

Et, si cet objet a sémantique de valeur (qu'il est copiable, et affectable, et qu'il ne fait partie d'aucune hiérarchie de classe), on peut parfaitement envisager l'utilisation de boost::any

Mais avant d'en arriver là, il y a malgré tout deux questions qu'il semble intéressant de se poser...

La première est celle du but que tu poursuis en plaçant une référence parfois sur un objet de type A, parfois sur un objet de type B, ou C ou D.

Est-ce que c'est pour que ta classe Z puisse les manipuler "en interne" (comprend : que l'utilisateur puisse tout ignorer de A, B, C et D quand il manipule Z, une fois qu'elle a été correctement "initialisée"), ou est-ce pour que Z puisse fournir un accès à l'objet référencé

La deuxième question est de savoir s'il est vraiment "utile et opportun" de pouvoir disposer, en même temps de deux objets de type Z dont l'un référence un A et l'autre un B (ou un C ou un D)

Si tu envisages de ne travailler, à un moment donné, uniquement avec des objets de type Z qui manipulent des A OU uniquement avec des objets de type Z qui ne manipulent que des B (ou C ou D, encore une fois ), un Z<A> devra surement fournir la même interface public qu'un Z<B> ou qu'un Z<C> (ou encore qu'un Z<D>) -- et bien sur, adapter le "comportement interne" au fait qu'il manipule un A, un B, un C ou un D -- mais il n'est pas forcément utile que les quatre solutions aient une base commune. On peut alors très bien envisager de travailler de manière générique avec, d'une part, un "helper" template, spécialisée pour travailler respectivement avec un A, un B, un C ou un D sous une forme proche de
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
template <typename Type>
class MyHelper;
template <>
class MyHelper<A>
{
    typeDeRetour operator()(A const & a)
    {
        /* traitement spécifique à A */
    }
};
template <>
class MyHelper<B>
{
    typeDeRetour operator()(B const & b)
    {
        /* traitement spécifique à B */
    }
};
template <>
class MyHelper<C>
{
    typeDeRetour operator()(C const & c)
    {
        /* traitement spécifique à C */
    }
};
template <>
class MyHelper<D>
{
    typeDeRetour operator()(D const & d)
    {
        /* traitement spécifique à D */
    }
};
et de créer une classe générique pour Z proche de
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template <typename Type>
class Z
{
    public:
        /* note que cela fonctionne aussi parfaitement avec des références
         * et que l'idéal serait carrément de travailler avec des pointeurs
         * intelligents s'il faut vraiment que l'objet référencé soit un pointeur ;)
         */
        Z(Type * pointer):pointer_(pointer){}
        typeDeRetour doSomething() /* const */
        {
             return MyHelper<Type>()(*pointer_);
        }
        /* et l'on peut même envisager de renvoyer l'objet référencé,
         * sous a forme d'une référence (constante ou non) ou d'un pointeur ;)
         */
        /* const */ Type & referedObject() /* const */
        {
            return *pointer_;
        }
    private:
        Type * pointer_;
};
Note d'ailleurs que si tu veux pouvoir manipuler en même temps des Z qui référencent des A et d'autres qui référencent des B, des C ou des D, cette classe peut, au pris de quelques aménagements, t'éviter de recopier trop souvent du code

On garderait les "helpers" tels que je les ai décrit plus haut, et l'on utiliserait le pattern NVI sous une forme proche de
Code :
1
2
3
4
5
6
7
8
9
class ZBase
{
    public:
    /* ... */
        typeDeRetour something() /* const*/
        { return doSomething();}
    private:
        typeDeRetour doSomething() /* const */ = 0;
};
dont hériterait notre classe template Z sous une forme proche de
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
template <typename Type>
class Z :public ZBase
{
    public:
        /* note que cela fonctionne aussi parfaitement avec des références
         * et que l'idéal serait carrément de travailler avec des pointeurs
         * intelligents s'il faut vraiment que l'objet référencé soit un pointeur ;)
         */
        Z(Type * pointer):pointer_(pointer){}
        /* et l'on peut même envisager de renvoyer l'objet référencé,
         * sous a forme d'une référence (constante ou non) ou d'un pointeur ;)
         *
         * ...Après avoir pu déterminer si Z manipule un A, un B, un C ou un D
         */
        /* const */ Type & referedObject() /* const */
        {
            return *pointer_;
        }
    private:
 
        typeDeRetour doSomething() /* const */
        {
             return MyHelper<Type>()(*pointer_);
        }
        Type * pointer_;
};
Voilà, je crois avoir exploré toutes les pistes possibles, ou, du moins, toutes celles qui me venaient à l'esprit.

Je vais donc m'en arrêter là avant d'écrire un roman, mais n'hésites pas à demander plus d'information si tu ne comprends pas une chose ou l'autre
__________________
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
je ne répondrai à aucune question technique par E-mail, message visiteur ou message privé
Vous avez obtenu votre réponse pensez au bouton en bas de page
koala01 est actuellement connecté   Envoyer un message privé Réponse avec citation 20
Vieux 21/11/2012, 10h59   #3
mulfycrowh
Invité régulier
 
Inscription : janvier 2006
Messages : 155
Détails du profil
Informations forums :
Inscription : janvier 2006
Messages : 155
Points : 8
Points : 8
Merci pour ta réponse.
Je comprends dans la globalité.
Ne serait il pas plus simple dans la classe Z d'avoir comme attributs :

A* A_pointer;
B* B_pointer;
C* C_pointer;
D* D_pointer;

et de documenter le pointeur correspondent suivant le type d'objet A, B, C ou D. Les autres seraient dcumentés avec NULL ?
mulfycrowh est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/11/2012, 14h27   #4
koala01
Modérateur
 
Avatar de koala01
 
Philippe Dunski
Inscription : octobre 2004
Messages : 8 612
Détails du profil
Informations personnelles :
Nom : Philippe Dunski
Âge : 41

Informations forums :
Inscription : octobre 2004
Messages : 8 612
Points : 13 287
Points : 13 287
Envoyer un message via MSN à koala01 Envoyer un message via Skype™ à koala01
En terme de facilité, c'est discutable, car tu devrais alors prévoir quatre constructeur, ou les quatre mutateurs directement, avec la difficulté de t'assurer, si tu fournis les mutateurs, que les pointeurs sont tous remis à NULL au moment où tu change de type.

De plus, si ta classe utilise elle-même les pointeurs en interne, tu seras obligé de tester les quatre pointeurs pour savoir lequel référence un objet.

Par contre, en terme d'évolutivité, ce serait une catastrophe

Si tu viens, dans quelques mois, à vouloir rajouter une classe E ou une classe F parce que tes besoins ont évolué, tu devras revoir l'intégralité du code de Z, avec le risque d'oublier quelque chose

Avec la solution basée sur un helper, tu n'auras qu'à le spécialiser pour ta nouvelle classe et le tour sera joué (sans avoir à toucher au code existant).

De plus, si tu viens à avoir plusieurs helpers exécutant des choses différentes (car, en gros, il y en aura un par comportement ), et que tu en oublies un, tu auras directement une erreur de compilation t'indiquant que tu as oublié de le définir
__________________
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
je ne répondrai à aucune question technique par E-mail, message visiteur ou message privé
Vous avez obtenu votre réponse pensez au bouton en bas de page
koala01 est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/11/2012, 16h02   #5
mulfycrowh
Invité régulier
 
Inscription : janvier 2006
Messages : 155
Détails du profil
Informations forums :
Inscription : janvier 2006
Messages : 155
Points : 8
Points : 8
Merci.
Pourrions nous expliciter la première approche du helper qui me paraît plus simple.

Pourquoi dans la classe template MyHelper fais tu une surcharge d'opérateur ? Qu'entends tu par "traitement spécifique à ..." ?
mulfycrowh est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/11/2012, 16h24   #6
koala01
Modérateur
 
Avatar de koala01
 
Philippe Dunski
Inscription : octobre 2004
Messages : 8 612
Détails du profil
Informations personnelles :
Nom : Philippe Dunski
Âge : 41

Informations forums :
Inscription : octobre 2004
Messages : 8 612
Points : 13 287
Points : 13 287
Envoyer un message via MSN à koala01 Envoyer un message via Skype™ à koala01
Citation:
Envoyé par mulfycrowh Voir le message
Pourquoi dans la classe template MyHelper fais tu une surcharge d'opérateur ?
Pour avoir ce que l'on appelle un foncteur (ou un objet fonction):

Une classe qui ne contient qu'une seule fonction que l'on peut appeler à l'aide des (), sous une forme proche de
Code :
1
2
3
4
5
/* on crée la variable que le foncteur utilise */
A myObject;
/* on crée une variable du type foncteur */
MyHelper<A> helper;
helper(myObject);
C'est une manière particulièrement efficace de travailler quand tu envisage des alogrithmes dont la seule différence est, finalement, la donnée sur laquelle le traitement est effectué.

Par exemple, si tu envisage d'avoir un tableau de A, et que tu veux parfois le trier sur A.truc() et parfois sur A.machin(), tu peux très bien envisager d'avoir un foncteur qui comparera first.truc() à second.truc() et un autre qui comparera first.machin() à second.machin() afin de savoir, dans les deux cas, lequel est le plus petit.

Le tri pourra alors se faire en une seule ligne grace à la fonction sort, disponible (comme tout ce qui est fourni par le standard) dans l'espace de nom std par simple inclusion du fichier d'en-tête <algorithm> sous la forme de
Code :
1
2
3
4
5
6
7
8
9
10
11
 
/* avec le foncteur LessByTruc sous la forme de
struct LessByTruc
{
    bool operator()(A const & first, A const & second) const
    {
        return first.truc() <second.truc();
    }
};
*/
std::sort(tab.begin(), tab.end(), LessByTruc());
si tu veux le trier en fonction du résultat de a fonction truc() ou de
Code :
1
2
3
4
5
6
7
8
9
10
11
 
/* avec le foncteur LessByTruc sous la forme de
struct LessByMachin
{
    bool operator()(A const & first, A const & second) const
    {
        return first.machin()<second.machin();
    }
};
*/
std::sort(tab.begin(), tab.end(), LessByMachin());
si tu veux le trier en fonction du résultat de a fonction machin()
Citation:
Qu'entends tu par "traitement spécifique à ..." ?
Tout simplement : tout ce que tu peux envisager de faire avec un objet de type A, B, C ou D en fonction du type de l'objet que tu manipules

Si les classes A, B, C et D n'ont aucune relation d'héritage, il y a fort à parier (même si ce n'est pas forcément certain ) qu'elles présenteront des fonctions publiques différentes, et que tu les manipuleras donc de manière différentes

Le "traitement spécifique à..." correspond à tout ce qui sera propre à ton objet de type A, B, C ou D et qui n'est pas forcément utilisable avec les autres types
__________________
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
je ne répondrai à aucune question technique par E-mail, message visiteur ou message privé
Vous avez obtenu votre réponse pensez au bouton en bas de page
koala01 est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/11/2012, 16h46   #7
mulfycrowh
Invité régulier
 
Inscription : janvier 2006
Messages : 155
Détails du profil
Informations forums :
Inscription : janvier 2006
Messages : 155
Points : 8
Points : 8
Si tu permets nous allons expliciter un peu.
Il s'agit d'une partition de musique.

Ma classe Z est la classe MESURE qui contient pour attributs :

- son numéro
- un vecteur de pointeurs sur la classe SYMBOLE


Un symbole peut être de type NOTE, TEXTE ou ICONE. Il s'agit donc de 3 classes (pas 4 ) qui ont leurs propres constructeurs, destructeurs et attributs.
Lorsque je vais balayer ma partition, je vais par exemple rencontrer une clef de Fa qui esr de type ICONE. Je vais donc instancier ICONE et récolter un pointeur.
Comment dois je définir la classe SYMBOLE et la classe MyHelper pour dire à la classe SYMBOLE que mon premier symbole est de type ICONE et qu'il pointe vers la clef de Fa ?
mulfycrowh est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/11/2012, 16h58   #8
leternel
Expert Confirmé
 
Homme Pierre
Ingénieur développement logiciels
Inscription : juin 2007
Messages : 1 185
Détails du profil
Informations personnelles :
Nom : Homme Pierre
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : juin 2007
Messages : 1 185
Points : 2 500
Points : 2 500
et tu ne peux pas avoir une classe de base (affichable ou autre)?
__________________
Mes principes de bases du codeur qui veut pouvoir dormir:
  • Une variable de moins est une source d'erreur en moins.
  • Un pointeur de moins est une montagne d'erreurs en moins.
  • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
  • La plus sotte des questions est celle qu'on ne pose pas.
leternel est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/11/2012, 17h11   #9
mulfycrowh
Invité régulier
 
Inscription : janvier 2006
Messages : 155
Détails du profil
Informations forums :
Inscription : janvier 2006
Messages : 155
Points : 8
Points : 8
Au départ, j'ai créé une classe instrument qui a des classes filles :

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
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
class score_part
{
public:
 
// **********************************************************
// * structs    											*
// **********************************************************
struct struct_transpose
{
	int						diatonic;
	int						chromatic;
};
 
 
struct struct_time_signature
{
	int						beats;
	int						beat_type;
};
 
 
struct struct_key_signature
{
	int						sharp;
	int						flat;
	int						natural_on_sharp;
	int						natural_on_flat;
};
 
 
struct struct_metronome
{
	const pugi::char_t*		beat_unit;
	int						per_minute;
};
 
struct struct_symbol_location
{
	int						measure;
	int						default_x;
	int						default_y;
};
 
	score_part::score_part(const pugi::char_t* _score_part_id, const pugi::char_t*_part_name, const pugi::char_t* _part_name_display_text,
						   const pugi::char_t* _part_abbreviation, const pugi::char_t* _part_abbreviation_display_text, const pugi::char_t* _score_instrument_id,
					       const pugi::char_t* _instrument_name, part_group* part_group_pointer);
	~score_part(void);
 
	const pugi::char_t*										score_part_id;
 
	static const pugi::char_t*								clef_symbol_bak;
	static struct_time_signature							time_signature_symbol_bak;
	static struct_key_signature								key_signature_symbol_bak;
	static struct_metronome									metronome_symbol_bak;
 
 
 
	void													extract_attribute(pugi::xml_node_iterator iterator);
 
 
private:
 
	// classes
	class clef
	{
		public:
 
		clef(const pugi::char_t* _symbol, int _measure, const pugi::char_t* _color);
		~clef(void);
 
		private:
 
		const pugi::char_t*									symbol;
		const pugi::char_t*									color;
		int													measure;
		unsigned long int									x;
	};
 
	class time_signature
	{
		public:
 
		time_signature(struct_time_signature _symbol, int _measure, const pugi::char_t* _color);
		~time_signature(void);
 
		private:
 
		struct_time_signature								symbol;
		const pugi::char_t*									color;
		int													measure;
 
	};
 
	class key_signature
	{
		public:
 
		key_signature(struct_key_signature _symbol, int _measure, const pugi::char_t* _color);
		~key_signature(void);
 
		private:
 
		struct_key_signature								symbol;
		const pugi::char_t*									color;
		int													measure;
 
	};
 
	class metronome
	{
		public:
 
		metronome(struct struct_metronome _symbol, int _measure, int _default_y, const pugi::char_t* _color, const pugi::char_t* _font_family,
			      const pugi::char_t* _font_style, float _font_size, const pugi::char_t* _font_weight);
		~metronome(void);
 
		struct_metronome									symbol;
		const pugi::char_t*									color;
		int													default_y;
		const pugi::char_t*									font_family;
		const pugi::char_t*									font_style;
		float												font_size;
		const pugi::char_t*									font_weight;
		int													measure;
 
	};
 
	class word
	{
		public:
 
		word(int _measure, int _default_x, int _default_y, int _relative_x, int _relative_y, const pugi::char_t* _justify, 
			 const pugi::char_t* _valign, const pugi::char_t* _font_family, const pugi::char_t* _font_style, 
		     float _font_size, const pugi::char_t* _font_weight, const pugi::char_t* text);
	    ~word(void);
 
		private:
 
		int													measure;
		int													default_x;
		int													default_y;
		int													relative_x;
		int													relative_y;
		const pugi::char_t*									justify;
		const pugi::char_t*									valign;
		const pugi::char_t*									font_family;
		const pugi::char_t*									font_style;
		float                                               font_size;
		const pugi::char_t*									font_weight;
		const pugi::char_t*									text;
 
	};
 
	class dynamics
	{
		public:
 
		dynamics(int _measure, int _default_x, int _default_y, const pugi::char_t* _color, const pugi::char_t* _font_family,
			     const pugi::char_t* _font_style, float _font_size, const pugi::char_t* _font_weight, const pugi::char_t* symbol);
		~dynamics(void);
 
		private:
 
		int													measure;
		int													default_x;
		int													default_y;
		const pugi::char_t*									color;
		const pugi::char_t*									font_family;
		const pugi::char_t*									font_style;
		float												font_size;
		const pugi::char_t*									font_weight;
		const pugi::char_t*									symbol;
 
	};
 
	class symbol
	{
		public:
 
		symbol(struct_symbol_location _symbol_begin, struct_symbol_location _symbol_end,const pugi::char_t* _color, const pugi::char_t* _symbol_name);
		~symbol(void);
 
		struct_symbol_location                               symbol_end;	
 
		private:
 
		const pugi::char_t*									color;
		struct_symbol_location								symbol_begin;
		const pugi::char_t*									symbol_name;
 
 
	};
 
 
	void													extract_transpose(pugi::xml_node_iterator iterator);
	void													extract_clef(pugi::xml_node_iterator iterator);
	void													extract_time_signature(pugi::xml_node_iterator iterator);
	void													extract_staff(pugi::xml_node_iterator iterator);
	void													extract_key_signature(pugi::xml_node_iterator iterator);
	void													extract_direction(pugi::xml_node_iterator iterator);
	void													extract_metronome(int measure,pugi::xml_node* metronome_node);
	void													extract_word(int measure,pugi::xml_node* word_node);
	void													extract_dynamics(int measure,pugi::xml_node* dynamics_node);
	void													extract_wedge(int measure,pugi::xml_node* wedge_node);
	void													extract_pedal(int measure,pugi::xml_node* pedal_node);
 
	const pugi::char_t*										part_name;
	const pugi::char_t*										part_name_display_text;
	const pugi::char_t*										part_abbreviation;
	const pugi::char_t*										part_abbreviation_display_text;
	const pugi::char_t*										score_instrument_id;
	const pugi::char_t*										instrument_name;
	struct_transpose										transpose;
 
	// pointers to classes
	part_group*												part_group_pointer;
	std::vector<clef*>										clef_pointer;
	std::vector<time_signature*>							time_signature_pointer;
	std::vector<key_signature*>								key_signature_pointer;
	std::vector<metronome*>									metronome_pointer;
	std::vector<word*>										word_pointer;
	std::vector<dynamics*>									dynamics_pointer;
	std::vector<symbol*>									symbol_pointer;
 
	// counts
	int														clef_count;
	int														time_signature_count;
	int														staff_count;
	int														key_signature_count;
	int														metronome_count;
	int														word_count;
	int														dynamics_count;
	int														symbol_count;
 
 
 
};
Mais je trouve cela très lourd. D'autre part, je me suis rendu compte que de nombreux symboles pouvaient être regroupés
mulfycrowh est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/11/2012, 18h37   #10
koala01
Modérateur
 
Avatar de koala01
 
Philippe Dunski
Inscription : octobre 2004
Messages : 8 612
Détails du profil
Informations personnelles :
Nom : Philippe Dunski
Âge : 41

Informations forums :
Inscription : octobre 2004
Messages : 8 612
Points : 13 287
Points : 13 287
Envoyer un message via MSN à koala01 Envoyer un message via Skype™ à koala01
En fait, cela me fait furieusement penser à une discussion (ouverte par toi, d'ailleurs) à laquelle j'ai répondu il n'y a pas si longtemps et dans laquelle je présentais une conception possible pour la notion de partition (et pour laquelle tu n'as jamais répondu, soit dit en passant )...

Peut etre pourrais tu te baser sur ma prose en considérant qu'un instrument est, quoi qu'il arrive, un instrument, même si certains (comme le piano ou la guitare) permettent de jouer plusieurs notes en même temps et que d'autres (comme les instruments à vent de manière générale) ne permettent que d'en jouer une seule...

Tu pourrais alors considérer que chaque instrument dispose de sa propre partition, mais que la partition n'a aucun besoin de pouvoir dire à quel instrument elle est reliée

Comme je l'ai fait remarquer dans l'intervention que je cite ici, tu dois clairement faire la différence entre ta partie "métier" (les instruments, les notes, les partitions et tout le saint frusquin) et la partie qui s'occupe de les afficher d'une manière ou d'une autre.

Les classes que je présentais à l'occasion de cette intervention fournissent normalement tout ce qui te sera nécessaire pour l'affichage (ou peu s'en faut), sous n'importe quelle forme, étant entendu que ce n'est ni à l'instrument, ni à la partition, ni au note ni à quoi que ce soit d'autre issu de la partie "métier" de prendre en charge une quelconque responsabilité d'affichage.

En effet, si tu décides de donner la responsabilité de l'affichage aux éléments de ta partie "métier", tu contreviens à plusieurs principes considérés comme les "piliers de base" de la programmation orienté objects que l'on connait sous l'aconyme de SOLID(dont, au minimum, le S, en l’occurrence )

En séparant clairement ta vue (ton affichage) de ton modèle (la partie métier), tu prendras la voie d'un respect de l'ensemble de ces principes, et tu te mettras en position de faire évoluer beaucoup plus facilement ton application
__________________
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
je ne répondrai à aucune question technique par E-mail, message visiteur ou message privé
Vous avez obtenu votre réponse pensez au bouton en bas de page
koala01 est actuellement connecté   Envoyer un message privé Réponse avec citation 10
Vieux 21/11/2012, 21h57   #11
mulfycrowh
Invité régulier
 
Inscription : janvier 2006
Messages : 155
Détails du profil
Informations forums :
Inscription : janvier 2006
Messages : 155
Points : 8
Points : 8
Merci beaucoup pour tous ces conseils
mulfycrowh est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 16h11.


 
 
 
 
Partenaires

Hébergement Web