Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2290 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  Ecrire structure dans un fichier + héritage

 



 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Ecrire structure dans un fichier + héritage

n°438456
Willyzekid
Posté le 24-06-2003 à 20:17:18  profilanswer
 

Je veux écrire le contenu de plusieurs structures dans un fichier. J'ai le code suivant qui définit une structure B dérivant de A avec un peu de polymorphisme:
 

Code :
  1. struct A {
  2.     unsigned long m_ID;
  3.    
  4.     virtual int byteRead() = 0;
  5. }
  6. struct B : public A {
  7.     unsigned long m_Index1;
  8.     unsigned long m_Type;
  9.     int byteRead() {..}
  10. }


 
quand je fais un bête

Code :
  1. ofstream file(....);
  2. B objB;
  3. file.write(reinterpret_cast<const char*>(&objB), sizeof(objB));


 
ca ne devrait bien sur pas marcher parce que sizeof(objB) contient AUSSI d'autres info (type la taille du pointer sur la fontion byteRead?)...Y a t-il une solution, sachant que j'ai absolument besoin du polymorphisme pour connaître le type exact de ma variable une fois downcasté!
 
Sais pas si c'est clair....


Message édité par Willyzekid le 24-06-2003 à 20:22:44

---------------
Horizon pas Net, reste à la buvette!!
mood
Publicité
Posté le 24-06-2003 à 20:17:18  profilanswer
 

n°438459
Joel F
Real men use unique_ptr
Posté le 24-06-2003 à 20:24:55  profilanswer
 

Fait toi une methode virtuelle pure 'write' dans tes objets.
 

Code :
  1. struct A {
  2.    unsigned long m_ID;
  3.  
  4.    virtual int byteRead() = 0;
  5.    virtual void write(ofstream os)
  6.   {
  7.      os << m_ID;
  8.   }
  9. }
  10. struct B : public A {
  11.    unsigned long m_Index1;
  12.    unsigned long m_Type;
  13.    int byteRead() {..}
  14.    virtual void write(ofstream os)
  15.   {
  16.      A::write(os);
  17.      os << m_Index1 << m_Type;
  18.   }
  19. }

n°438463
Willyzekid
Posté le 24-06-2003 à 20:35:12  profilanswer
 

Joel F a écrit :

Fait toi une methode virtuelle pure 'write' dans tes objets.


 
Ouais, c'est ce que j'ai fait mais le truc c'est qu'après plusieurs dérivation, j'arrive a avoir une bonne dizaine (voire plus) de champs dans mes classes.
Du coup, j'aimerais les écrire tous en un seul bloc, avec un seul appel à write() pour optimiser les perf. Ca veut dire connaitre le pointeur sur le début des données en mémoire, et la taille de celles-ci.
 
Idem pour read...
 
C'est d'autant plus important que je peux parcourir un fichier de plusieurs millions de records comme ca pour les extraires l'un après l'autre et lire la valeur d'un des champs (ie. utilisation database).
 
Merci quand même!


---------------
Horizon pas Net, reste à la buvette!!
n°438491
youdontcar​e
Posté le 24-06-2003 à 21:20:12  profilanswer
 

Un truc utilisé dans Half-Life et les MFC (et un peu partout je crois) : mettre une table statique par niveau de dérivation pour définir toutes les variables exportables d'une classe. eg :
 
class a
{
  int varA;
  int varB;
 
};
 
defineTableVars(a)
  defineVar("int", offsetof(class a, varA))
  defineVar("int", offsetof(class a, varB))
defineTableVars(a)
 
class b : public a
{
  char c;
 
  defineTable(b, a)
};
 
defineTableVars(b)
  defineVar("char", offsetof(class b, varC))
defineTableVars(b)
 
Une fois que tu as ça, tu peux constituer pour chaque classe un tableau statique de tout ce qu'elle peut contenir, importer / exporter automatiquement, scripter, etc. Tu n'as plus qu'à parser ce tableau d'offsets pour sérialiser toutes les données de la classe dans un bloc.  
 
Ce genre de système te permet également le versioning : si tu ne fais pas ça comme un gros goret (eg tu checkes le nom de la variable à chaque écriture), tu peux rajouter / enlever des variables de tes classes à loisir, sans péter les formats des fichiers existants.

n°438525
Willyzekid
Posté le 24-06-2003 à 22:33:03  profilanswer
 

youdontcare a écrit :

Un truc utilisé dans Half-Life et les MFC (et un peu partout je crois) : mettre une table statique par niveau de dérivation pour définir toutes les variables exportables d'une classe. eg :
(...)
Ce genre de système te permet également le versioning : si tu ne fais pas ça comme un gros goret (eg tu checkes le nom de la variable à chaque écriture), tu peux rajouter / enlever des variables de tes classes à loisir, sans péter les formats des fichiers existants.


 
Tiens c'est la première fois que je vois ca...Faut dire que je me plonge pas dans du MFC à longueur de journée! :o
 
Sinon, je suis pas sûr que ca règle mon problème s'il faut parser tous les offsets. Ca revient a faire un appel a ofstream::write() pour chaque variable.
 
Cela dit, je dois t'avouer que comme je comprends pas ce que fait defineTableVars(a), etc... C'est une macro? tu l'as sous la main?


---------------
Horizon pas Net, reste à la buvette!!
n°438531
youdontcar​e
Posté le 24-06-2003 à 22:45:01  profilanswer
 

>> Sinon, je suis pas sûr que ca règle mon problème s'il faut parser tous les offsets. Ca revient a faire un appel a ofstream::write() pour chaque variable.
 
Ça dépend. Une optim de ce code est de dumper tout l'objet sans la vtable ( ((char*)this)+4, sizeof(*this)-4) et d'écrire tout d'un coup. Tu sauvegardes une seule description des données par classe. Au chargement, tu peux relire ça similairement si la structure enregistrée correspond à la structure runtime.
 
Mais faut pas te leurrer, soit tu fais un truc hypra simple (que des structures) qui explosera lamentablement au moindre changement d'une structure, soit tu fais un truc clean. (sauvegarde des noms des variables, test, etc.) Et avant de dire que c'est lent, tu benches :D
 
Je ne sais pas comment bosse ofstream, s'il écrit sur le dur à chaque appel, c'est mal. Un bon buffer mémoire remédie à ça.
 
>> Cela dit, je dois t'avouer que comme je comprends pas ce que fait defineTableVars(a), etc... C'est une macro? tu l'as sous la main?
 
Oui. C'est pour t'encourager à chercher par toi-même, car je n'ai pas ça sous la main. Comme je l'ai dit, un tableau statique par niveau de dérivation.  
 
* Une macro dans la définition de la classe pour ... définir la table (defineTable)
* Une macro pour implémenter la table (defineTableVars)
* Une macro pour définir chaque variable (defineVar)

n°438537
Joel F
Real men use unique_ptr
Posté le 24-06-2003 à 22:49:39  profilanswer
 

[:violon] suis je le seul a trouver ca moche ???

n°438663
LetoII
Le dormeur doit se réveiller
Posté le 25-06-2003 à 09:00:47  profilanswer
 

Joel F a écrit :

[:violon] suis je le seul a trouver ca moche ???


 [:plusun]  
 
C hyper crade, hyper pas portable.


---------------
Le Tyran
n°438667
LeGreg
Posté le 25-06-2003 à 09:17:51  profilanswer
 

Ce qu'on faisait dans ma precedente boite
c'est que pour chaque classe on creait une instance
vide de la classe, tout simplement pour pouvoir copier le pointeur vers la vtable et pouvoir identifier les classes que l'on allait charger (identifiées par des metaobjets representant les classes).  
 
Bien evidemment sur console il n'y avait pas forcément de fixup des pointeurs si l'on se contentait d'un chargement par overlay.
Sur PC il etait necessaire de fixuper les pointeurs par contre.
 
LeGreg

n°438693
LetoII
Le dormeur doit se réveiller
Posté le 25-06-2003 à 09:41:45  profilanswer
 

legreg a écrit :

Ce qu'on faisait dans ma precedente boite
c'est que pour chaque classe on creait une instance
vide de la classe, tout simplement pour pouvoir copier le pointeur vers la vtable et pouvoir identifier les classes que l'on allait charger (identifiées par des metaobjets representant les classes).  
 
Bien evidemment sur console il n'y avait pas forcément de fixup des pointeurs si l'on se contentait d'un chargement par overlay.
Sur PC il etait necessaire de fixuper les pointeurs par contre.
 
LeGreg


 
Argh c encore pire  :cry:


---------------
Le Tyran
mood
Publicité
Posté le 25-06-2003 à 09:41:45  profilanswer
 

n°438707
Joel F
Real men use unique_ptr
Posté le 25-06-2003 à 09:56:37  profilanswer
 

Des fois je me demande pourquoi y a des gens compétents qui se sont fait iech à inventer l'héritage tout ca ...
 
M'enfin, ....

n°438710
LetoII
Le dormeur doit se réveiller
Posté le 25-06-2003 à 09:58:39  profilanswer
 

Attend j'en ai une encore pire: tu mape ton fichier en mémoire et tu fai un new de palcement avec el constructeur de recopie  
 
 :pt1cable:


---------------
Le Tyran
n°438712
Joel F
Real men use unique_ptr
Posté le 25-06-2003 à 10:00:24  profilanswer
 

LetoII a écrit :

Attend j'en ai une encore pire: tu mape ton fichier en mémoire et tu fai un new de palcement avec el constructeur de recopie  
 
 :pt1cable:  


 
 :lol:  :lol:  :pt1cable:  
Arrete on dirait du code de kitusais !!

n°438727
LetoII
Le dormeur doit se réveiller
Posté le 25-06-2003 à 10:13:28  profilanswer
 

Joel F a écrit :


 
 :lol:  :lol:  :pt1cable:  
Arrete on dirait du code de kitusais !!


 
je vois pas dekituparle  :??:


---------------
Le Tyran
n°439103
Willyzekid
Posté le 25-06-2003 à 15:09:58  profilanswer
 

Bon les enfants, vous auriez pas un truc portable. Non parce que j'ai aussi pensé à jouer avec la vtable mais là, c'est non seulement ca dépend de l'os mais ca commence aussi à dépendre du compilo.
 
Et moi, comble du programmeur, j'ai besoin d'un truc portable :)
 
J'en reviens effectivement pas qu'il n'y ait rien de prévu dans les spécifications... :(


---------------
Horizon pas Net, reste à la buvette!!
n°439110
LetoII
Le dormeur doit se réveiller
Posté le 25-06-2003 à 15:14:43  profilanswer
 

Utilise un stringstream (je sais plus le nom exact de la classe)
 
Tu écrit tout t champ dedans et après tu écrit ta chaine dans un fichier.
Si tu veux faire du binaire tu écrit tout t champ dans un buffer (pense à fixer l'indianess) et écrit le buffer dans le fichier (encore que du binaire avec un ftream faut envouloir)


---------------
Le Tyran
n°439207
Willyzekid
Posté le 25-06-2003 à 15:54:20  profilanswer
 

LetoII a écrit :

Utilise un stringstream (je sais plus le nom exact de la classe)
 
Tu écrit tout t champ dedans et après tu écrit ta chaine dans un fichier.
Si tu veux faire du binaire tu écrit tout t champ dans un buffer (pense à fixer l'indianess) et écrit le buffer dans le fichier (encore que du binaire avec un ftream faut envouloir)


 
Effectivement c'est du binaire que je veux, et non j'utilise pas la STL pour ça (suis pas maso). Je fais "une sorte de base de données" donc mes fonctions d'entrée sortie sont trés low level (à la limites des appels systèmes).
 
J'ai trouvé la solution élégante (dans mon cas)! En fait, je viens de refaire le design de plusieurs classes pour pouvoir utiliser des templates pour mes structures...sans dérivation. Ca me force a revoir la plupart du design sous un jour nouveau mais en même temps, ca règle pas mal de problème.
 
Exit l'héritage et le polymorphisme sur les struct A, B etc.
 
Merci en tout cas!


Message édité par Willyzekid le 25-06-2003 à 15:56:41

---------------
Horizon pas Net, reste à la buvette!!
n°439365
blackgodde​ss
vive le troll !
Posté le 25-06-2003 à 17:15:04  profilanswer
 

à la limites des appels systèmes
!=
portable (dans la plupart des cas)
 
il me semble en effet que plus on pousse l'optimisation, moins le code est portable, non ?


---------------
-( BlackGoddess )-
n°439439
LeGreg
Posté le 25-06-2003 à 18:20:16  profilanswer
 

la methode que j'ai cité etait
"relativement" portable.
 
En gros on avait 5 plateformes de destination:
Gamecube, Playstation 2, Xbox, Pc Windows, PC Linux.
 
Par un trick au chargement et a la sauvegarde
nos binaires etaient compatibles entre les differentes plateformes. (meme si on pouvait laisser tomber la compatibilité pour une plus grande performance)
 
Je ne fais pas une generalité mais sur console, typiquement, les chargements sont mieux s'ils sont reduits au minimum.
De plus si tu es limité a la taille de l'executable que tu peux charger en memoire tu utilises l'overlay (recouvrement d'une partie de la memoire en fonction des besoin).
Par ailleurs, contrairement au PC, d'un chargement a l'autre tu peux sauvegarder tes pointeurs, ou les fixuper en dur, tu es assuré qu'au prochain chargement, si tu fais bien les choses, les données de niveau que tu charges seront au meme emplacement mémoire (parfois tu es obligé quand tu as une rom plutot qu'une ram).
 
A+
LeGreg

n°439450
Willyzekid
Posté le 25-06-2003 à 18:36:33  profilanswer
 

BlackGoddess a écrit :

à la limites des appels systèmes
!=
portable (dans la plupart des cas)
 
il me semble en effet que plus on pousse l'optimisation, moins le code est portable, non ?


 
Oui mais je limite ces appels à un module/librairie "io" bien définie pour éviter de répercuter du code propriétaire à d'autres modules. D'autre part ce code reste un minimum portable gràce à des #define WIN32, etc. bien sentis
 
Les autres modules qui utilisent les fonctions de "io" n'ont pas à savoir comment c'est géré, et à utiliser du code propriétaire.


---------------
Horizon pas Net, reste à la buvette!!
n°439472
LeGreg
Posté le 25-06-2003 à 19:00:36  profilanswer
 

Citation :

ca ne devrait bien sur pas marcher parce que sizeof(objB) contient AUSSI d'autres info (type la taille du pointer sur la fontion byteRead?)...


 
Au chargement tu remplaces ton pointeur vers ta vtable
contre un offset vers un metachamp dans ton fichier qui va decrire ton type de données et en particulier le nom par exemple ou un hash quelconque qui ne change que si tu changes la version du fichier.
Ce metachamp va etre comparé au chargement au métachamp deja present dans les objets "vides" créés préalablement.
De cet objet vide tu vas récupérer le "vrai"pointeur vers la vtable.
 
Evidemment ca impose de connaitre un peu ton compilateur et de faire des #ifdef puisque malheureusement tous les compilateurs ne stockent pas leur pointeur de vtable au meme offset (certains utilisent un offset négatif !).
 
LeGreg

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  Ecrire structure dans un fichier + héritage

 

Sujets relatifs
caracteres a ne pas mettre dans le nom d'un fichier sur le net?[MySql] structure de table
J'arrive pas à écrire dans un fichier...besoin d'aidecombobox qui tape dans un fichier .txt sur le DD ou excel
Executer un fichier sur un ftp sous delphi?Comment décompresser un fichier avec une erreur CRC ?
Les fichier ressource ( .res ) en delphiOuverture d'un fichier sur le réseau
Récupération dans du code php du nom du fichier contenant le code ?exprimer une condition dans un fichier xsql
Plus de sujets relatifs à : Ecrire structure dans un fichier + héritage


Copyright © 1997-2018 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR