Bah quand je lis cela oui, c'est sur que ma solution c'est plus un très mauvais patch dans ce cas là, et qu'il y a un gros problème de conception...Envoyé par chrono23
Bah quand je lis cela oui, c'est sur que ma solution c'est plus un très mauvais patch dans ce cas là, et qu'il y a un gros problème de conception...Envoyé par chrono23
Merci laurent ca marche ton instruction! nickel!
Je veux bien qu'il ait un problème de conception, mais pourtant en théorie le concept d'héritage polymorphique, c'est exactement ce que j'ai fais!
Les objets prennent leur forme définitive que lors de l'éxecution d'ou l'interet de ces mecanismes!.
Mais si quelqu'un a une meilleures idée a me proposer je suis prenneur?
En résumé, je dois modéliser des paquets Mpeg-2, ces paquets contiennent divers d'objet, dont des "sections", il exsite différent types de sections.
Donc comme on ne connait le type de section que au fur et a mesure que la modelisation se fait on instancie le bon type de section a ce moment.
J'ai utilisé ce mécanismes aussi car je ne modèlise pas tous les types de sections tout de suite. Donc par souci de faciliter l'extension du code, il suffit de deriver la classe section, pour creer une section specifique!
est ce que je pourrais faire un cast au moment ou je sais quel type de sections ca va etre? par exemple:
est ce que cette instruction aura pour effet de caster mon pointeur section en PATSection, et que ce pointeur reste en PATSection????
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 static_cast<PATSection*>(Section) = new PATSection();
Le problème c'est que les fonctions héritées doivent dans la majorité servir.
Et il ne faut pas avoir un fonctionB pour la class B, une fonctionC pour la class C, une functionD pour la class D, et que tu mets tout en virtuel dans la classA.
L'intérêt de l'héritage est minimal.... voir null.
Il faut arriver à synthétiser une functionBCD commune. Ensuite peut importe le type d'objet, tu appels functionBCD à chaque fois.
Que font exactement tes fonctions dans les classes sections ?
Elles cherchent à comparer divers frames pour voir le matching dans le temps et l'espace de la vidéo, (glissement de scène, zoom in/out...) ?
Que retournent-elles ?
J'ai laisser tomber l'histoire de faire des virtual partout c'est trop degeu!
Mes fonctions sont simplement des fonctions (Get et Set) qui renvoit la valeur d'un champs, ou qui modifie la valeur d'un champ!
Les sections ont des champs en comment qui se trouve dans la sections mere, et les sections derivées ne possedent pas toutes les meme champs, d'ou le fait qu'elles n'ont pas les meme methode d'acces (Get et Set) puisque les champs sont différents.
Tu peux différencier les données des traitements.Envoyé par chrono23
Ensuite les fonctions de moteurs
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 class Adata Class Bdata:public Adata Class Cdata:public Adata Class Ddata:public Adata
Enfin quelque chose dans le style.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 class Aengine { virtual void Set(Adata*)=0; virtual Adata* Get()=0; } Class Bengine:public Aengine Class Cengine:public Aengine Class Dengine:public Aengine
Pas vraiment.Envoyé par chrono23
Ce que les gens sous-entendent par polymorphisme ("polymorphisme d'inclusion" dans le cas qui nous préoccupe ici), c'est que tu pourras demander un service à ton objet ton le type réel n'est pas entièrement définit dans le code d'appel. (pfff c'est très mal dit)Les objets prennent leur forme définitive que lors de l'éxecution d'ou l'interet de ces mecanismes!.
Mais si quelqu'un a une meilleures idée a me proposer je suis prenneur?
C'est ce que t'avais expliqué Ti-R deux messages plus loin (son avant-dernier message avant le mien -- désolé, le numéro n'est pas accessible depuis cette fenêtre de rédaction).
Seulement, tu prends ton problème de façon tout autre. Tu ne conçois pas en termes de services que tu peux rendre, mais en termes de données que tu stockes. Evidemment si les données que tu stockes sont différentes d'un fils à l'autre, tu es un peu marron.
Ou pas.. si tu réfléchis "service".
Quelque part, tu stockes des objets dont le type réel diffère. Ces objets doivent bien avoir un point commun pour que tu veuilles les stocker ensemble ?! Un traitement que tu veux réaliser sur tous, mais un traitement qui va en fait dépendre du type exact.
Alors plutôt que d'avoir une boucle externe qui va manipuler directement les données contenues, vois au contraire que tu as une boucle externe qui demande un service à chacun des objets stockés.
Et bien le polymorphisme d'inclusion en C++ (et même en Java et quelques autres langages similaires) est réalisé au travers de cette liaison tardive implémentée comme une fonction membre virtuelle : tous tes objets vont proposer un service qui sera spécialisé, et la boucle externe appelera le service sur chacun des objets.
Dans 95% des cas, c'est ainsi qu'il convient de procéder. Il reste quelques cas bien précis et connus où le C++ demande de réaliser explicitement des downcastings : désérialisation/factories (et encore, c'est loin d'être toujours nécessaire), polymorphisme sur plus d'un objet à la fois, ...
Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...
Je me demande si ce dont il a besoin ce n'est pas un mécanisme d'extension dans le domaine de la fonctionnalité plutôt que dans le domaine des classe; donc du double dispatch ou des visiteurs.Envoyé par Luc Hermitte
Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.
Ou alors la modification du comportement à l'exécution là ... mince c'est un DP que j'ai vu dans le bouquin du GoF ... on rajoute du comportement à la volée là.
Bref.
Quand au problème de l'auteur, je crois pas que l'héritage soit ici la solution, à moins que tu trouves une façon d'appeler la/les même(s) fonction(s), qui seront virtuelles dans la classe mère, mais qui dans les classes filles seront définies différemment, et qui selon les différentes sections agiront différemment. Si tu ne vois pas comment implémenter ça dans ta situation, ce n'est pas le polymorphisme d'inclusion qu'il te faut.
Mon blog anglais - Mes articles et critiques de livres - FAQ C++0x, avec liste des nouveautés - Conseils sur le C++ - La meilleure FAQ du monde - Avant de créer des classes que vous réutiliserez, regardez si ça n'existe pas déjà - Le site du comité de normalisation du C++
Le guide pour bien débuter en C++ - Cours et tutoriels pour apprendre C++
Waouuuu merci pour vos réponses les gars!
Alors pour le moment j'ai choisi une solutions qui n'est surement pas des plus propre mais qui a au moins le merite de fonctionner.
J'ai crée des méthodes dans la classe qui contient le pointeur de type statique de la classe mere qui posait probleme.
L'idée c'est que chacune des méthode va renvoyer le type de pointeur qu'il me faut sur le moment.
c'est une méthode du genre:
je sais pas ce que vous en pensez, mais je suis totalement ouvert aux critiques...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 SectionPAT* GetSectionPAT() { return dynamic_cast<SectionPAT*>(Section); }
Hum... Excuse-moi de revenir comme un cheveux sur la soupe, mais pourrais-tu montrer plus en détail comment fonctionne ta fonction, parce que j'ai un peu de mal, vu que son nom contient le nom de la classe réelle, il te faudra connaître le type de la classe réel (et donc faire le cast) avant d'appeller la fonction (où j'ai mal compris)...
Je pense également que tu devrais plutôt t'orienter vers un modèle de conception différent, n'hésite à expliquer en détail (même avec un exemple pour juste deux ou trois classes) ton problème, les spécialistes pourront te conseiller sur les DP à mettre en place et/ou les solutions "propres" à utiliser, tu peux même, dans l'absolue, aller faire un tour dans les forum Conceptions ...
Bon Courage lol
Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
pensez à la balise [ code ] (bouton #) et au tag (en bas)
Salut tous le monde!
Voila je vais refaire un petit topo ce qui c'est dit pour recentrer la discussion
et voir les solutions possibles par rapport a mon projet.
voici un schéma de mes classes (objet) et rapport entre eux dans le fichier joint.
je voudrai pouvoir acceder au aux champs des classe filles: j'imaginais une instrucction du style:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 mon pointeur d'objet déclarer de la classe mere ==> MpegSection* Section; Idem pour le descripteur. PaquetMpeg->paylaod->Section->Getchamps_SectionPAT();
Mais ceci n'est pas possible, donc il existe pulsieurs solutions que voici:
1|
faire des cast_dynamic
ca marche mais c'est pas tres beau
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 (dynamic_cast<SectionPAT*>(PaquetMpeg->payload->Section))->GetGetchamps_SectionPAT();
2|
idem une solution avec le cast_dynamic mais un peu plus jolie
dans la classe payload je declare une méthode qui me renvoit le pointeur casté.
ce qui assez semblable a l autre si c'est n'est qu on en voit pas le cast!
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 SectionPAT* GetSectionPATptr() { return dynamic_cast<SectionPAT*>(Section); } Puis je l utilise ainsi: (PaquetMpeg->payload->GetSectionPATptr())->GetGetchamps_SectionPAT();
et enfin 3 ieme solution qui est la moins bonne selon moi.
C'est de declarer toutes les methodes qui permette d'acceder a des champs specifique aux classes filles, en temps que classe abstraite dans la classe mere!
voila je crois que j'ai assez bien resumer, envoyent la structure de mes classes je suis ouvert a vos propsition de conception différente, mais je ne vois pas comment on pourrait faire autre chose...
Bonjour et merci pour la mise a jour chrono23,
Je me demande si tu ne pourrais pas en plus utiliser un retour par covariance.
Dans ta classe de base Section tu declare une methode :
Elle meme est redefinit dans toute tes classes filles comme suit par exemple :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 virtual Section * GetSection()
Ainsi lorsque tu appel GetSection(), il te retourne le bon type directement. Apres je sais pas si ca s'integre bien dans ton modele.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 SectionPAT * GetSection() { return this; }
(J'ai pas vraiment teste la solution, c est juste une idee en plus.)
Montre nous les fonctions qui utilisent ces classes dériées et contiennent ces écritures. Ce sont elles les plus importantes qui vont permettre de savoir si ton code peut être amélioré ou non.
Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...
Ok alors voici le constructeur de la classe payload, c'est dans ce dernier que se decide de quelles types sera la section, donc comment sera instancier mon pointeur Section.
juste le payload.h sinon on comprend pas tout:
le constructeur de Paylaod:
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 #pragma once #include "MpegSection.h" #include "PATSection.h" #include "PMTSection.h" #include "SectionCAT.h" #include "SectionNIT.h" #include <vector> using namespace std; class Payload { public: Payload(); Payload(char Data[], unsigned int DataLength, bool HasPointerField, unsigned int PID_courant); public: ~Payload(); public: //acces au donnés PayloadData unsigned char GetPayloadData(int Position); void SetPayloadData(int Position, unsigned char newPayloadData); MpegSection* GetSection(); PATSection* GetSectionPAT(); SectionCAT* GetSectionCAT(); SectionNIT* GetSectionNIT(); PMTSection* GetSectionPMT(); // pour récrire les données sous forme de fichier vector<unsigned char> serializePayload(); // champs de l'objet payload private: int PointerField; unsigned char* PayloadData; unsigned int PayloadDataLength; public: MpegSection* Section; };
Donc résumer un peu l'idée est de tester l'identifiant de la section et en fonctions de cela on choisit le types d'instanciation.
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 Payload::Payload() { PointerField = -1; PayloadData = 0; PayloadDataLength = 0; Section = 0; } // Constructeur de copie de Payload Payload::Payload(char Data[], unsigned int DataLength, bool HasPointerField, unsigned int PID_courant) { // initialisation des champs du payload // En cas de présence d'un PointerField on a un indice de décalage int indicePF = 0; PayloadDataLength = 0; PointerField = -1; PayloadData = 0; // présence d'un pointerField if (HasPointerField && (DataLength > 0)) { PointerField = (static_cast<unsigned int>(Data[0])) & 0xFF; PayloadDataLength = DataLength - 1; indicePF = 1; } else { PayloadDataLength = DataLength; } // présence d'une section de PAT // test la longueur du Payload, le tableID et le PID_courant if ((PayloadDataLength > 0) && (unsigned int(unsigned char(Data[PointerField+1])) == 0x00) && (PID_courant == 0x00)) { PayloadData = 0; // Les données de la section commence apres un intervalle d'octets de longueur PointerField //static_cast<PATSection*>(Section); Section = new PATSection(&Data[PointerField + 1]); } // Presence d'une PMT, on teste la longueur, le payload indicator et le TableID else if ((PayloadDataLength > 0) && (unsigned int(unsigned char(Data[PointerField+1])) == 0x02) && (HasPointerField)) { PayloadData = 0; // Les données de la section commence apres un intervalle d'octets de longueur PointerField Section = new PMTSection(&Data[PointerField + 1]); } // Presence d'une CAT, on teste la longueur, le payload indicator et le TableID else if ((PayloadDataLength > 0) && (unsigned int(unsigned char(Data[PointerField+1])) == 0x01) && (HasPointerField)) { PayloadData = 0; // Les données de la section commence apres un intervalle d'octets de longueur PointerField Section = new SectionCAT(&Data[PointerField + 1]); } // Presence d'une NIT, on teste la longueur, le payload indicator et le TableID else if ((PayloadDataLength > 0) && (((unsigned int(unsigned char(Data[PointerField+1])) == 0x40)||(unsigned int(unsigned char(Data[PointerField+1])) == 0x41)) && PID_courant == 0x10) && (HasPointerField)) { PayloadData = 0; // Les données de la section commence apres un intervalle d'octets de longueur PointerField Section = new SectionNIT(&Data[PointerField + 1]); } // si on a une section quelconque on copie les données dans un tableau PayloadData else { Section = new MpegSection(); PayloadData = new unsigned char[PayloadDataLength]; for (unsigned int i=0; i<PayloadDataLength;i++) { PayloadData[i] = Data[indicePF]; indicePF++; } } }
Comme vous pouvez le voir dans le header, j'ai implémenter les méthodes qui renvoit le pointeur de types correctes.
OK. Ceci est ta factory. C'est classique et ne répond toujours pas à ma question.
Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...
Ok désolé alors c'est que jâi pas compris ta question...
tu voulais que je te montre ce qui utilisais mes classes dérivées c'est bien ca?
alors je croyais que c'était ca? je suis pas contre un petit plus d'explication svp pour te donner exactement ce que tu veux??
C'est bien cela.Envoyé par chrono23
C'est toujours le même problème: à voir ton architecture, on se demande si une meilleure structure n'est pas possible. Avoir plus de détails sur l'architecture actuelle n'aide pas, il faut voir dans quel contexte elle est utilisée.
Un mécanisme de double dispatch me semble toujours être ce qu'il te faut, peut-être un visiteur sur la classe qui contient les Payload.
Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.
Je faisais allusion au code où tu utilises aujourd'hui le dynamic_cast. Soit le code utilisateur des objets déjà construits.
Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...
Et une conception orienté visiteur ne serait pas possible ? Préférable ?
Plus y'a d'Gruyère, plus y'a d'trous !
Plus y'a d'trous, moins y'a d'Gruyère...
Donc, Plus y'a d'Gruyère, moins y'a d'Gruyère !!!
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager