IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Mémorisation d'un pointeur


Sujet :

C++

  1. #1
    Membre du Club
    Inscrit en
    Janvier 2006
    Messages
    173
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 173
    Points : 42
    Points
    42
    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

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    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 : 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
    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 : 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
    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 : 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
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : 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
    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
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre du Club
    Inscrit en
    Janvier 2006
    Messages
    173
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 173
    Points : 42
    Points
    42
    Par défaut
    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 ?

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    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
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre du Club
    Inscrit en
    Janvier 2006
    Messages
    173
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 173
    Points : 42
    Points
    42
    Par défaut
    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 à ..." ?

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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()
    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
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Membre du Club
    Inscrit en
    Janvier 2006
    Messages
    173
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 173
    Points : 42
    Points
    42
    Par défaut
    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 ?

  8. #8
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    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.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  9. #9
    Membre du Club
    Inscrit en
    Janvier 2006
    Messages
    173
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 173
    Points : 42
    Points
    42
    Par défaut
    Au départ, j'ai créé une classe instrument qui a des classes filles :

    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
    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

  10. #10
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    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
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  11. #11
    Membre du Club
    Inscrit en
    Janvier 2006
    Messages
    173
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 173
    Points : 42
    Points
    42
    Par défaut
    Merci beaucoup pour tous ces conseils

Discussions similaires

  1. Réponses: 2
    Dernier message: 20/04/2010, 11h05
  2. Techniques mémorisation pointeurs ?
    Par peter27x dans le forum Débuter
    Réponses: 26
    Dernier message: 13/02/2009, 15h01
  3. [Turbo Pascal] Allocation et désallocation de pointeurs dans une fonction
    Par neird dans le forum Turbo Pascal
    Réponses: 13
    Dernier message: 17/11/2002, 20h14
  4. djgpp et pointeurs far -2
    Par elvivo dans le forum Autres éditeurs
    Réponses: 16
    Dernier message: 29/07/2002, 22h43
  5. djgpp et pointeurs far
    Par elvivo dans le forum C
    Réponses: 2
    Dernier message: 13/07/2002, 00h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo