Les dépendances cycliques dans l'inclusion se résolvent avec les forward déclarations, c'est à dire la déclaration de la classe (par opposition à sa définition)
Du moins, normalement.Code:class Bidule;
C'est d'ailleurs la nature même de <iosfwd>
Version imprimable
Les dépendances cycliques dans l'inclusion se résolvent avec les forward déclarations, c'est à dire la déclaration de la classe (par opposition à sa définition)
Du moins, normalement.Code:class Bidule;
C'est d'ailleurs la nature même de <iosfwd>
Oui les classe DerivedArchive et OTextArchive sont interpendantes entre elles vu qu'elle héritent toutes les deux les unes des autres, je sais pas si en c++ il y a moyen de gérer ce cas.
Car si j'ai besoin de la définition complète des deux classe pour pouvoir faire hériter l'une de l'autre ça va être compliqué. :X
Bref de toute façon comme mes archives contiennent aussi des méthodes template je vais retomber avec le même problème que prédédemment avec le serializer.
C'est à dire que même avec le wrapper je ne pourrai pas appeler les opérateur& des différents type d'archive car ceux-ci sont template.
J'ai pensé envoyé le wrapper à la méthode serialize mais je ne pourrai pas récupérer le type exact de l'archive car je ne le connais pas en compilation.
Je pensais donc revenir à ma première solution qui utlisait le polymorphisme statique.
Code:
1
2
3 Entity<Decor>* entity = new Decor(); Entity<Wall>* wall = new Wall();
Et qui je pense est la meilleur solution dans mon cas.
Le soucis c'est comment faire pour stocker ces différentes entités dans un conteneur et les sauver ?
Je peux pas faire une classe de base pour toutes les entités sinon je retombe toujours sur le même problème.
Sinon une solution crade c'est de faire ça :
Code:
1
2
3
4
5
6
7
8 for (unsigned int i = 0; i < entities.size(); i++) { if (entity[i]->getType() == "E_DECOR") { ar<<dynamic_cast<Entity<Decor>*>(entity[i]); } else if (entity[i]->getType() == "E_WALL") { ar<<dynamic_cast<Entity<Wall>*>(entity[i]); } }
Bon tant pis je suis revenu à mon ancienne solution :
http://www.developpez.net/forums/d14...serialisation/
Sincèrement je trouve que c'est la plus simple même si ce n'est pas la meilleur et puis je ne sais pas si elle est portable à cause du double pointeur de fonction ici :
Code:
1
2
3
4 template <typename A> void getSerializeFunc(void(O::**func)(A&)) { *func = &O::serialize; }
J'ai essayé de retourner le pointeur de fonction mais ça ne compile pas.
Fonction foo qui retourne un pointeur de fonction int(*)(T):
- int (*foo())(T)
- std::add_pointer_t<int(T)> foo()
- auto + decltype
Pour mettre des entités différentes dans un même conteneur, il faut une base commune: l'héritage.
Tu n'a pas l'air de comprendre qu'un moment ou un autre, les types réel seront perdu et seule l'entité le connaît. Ce n'est donc pas à l'archive d'écrire l'entité dans le fichier mais à l'entité d'écrire dans le fichier.
Au final j'ai du mal à comprendre se qui coince ; pour moi la sérialisation n'est ni plus ni moins aussi simple qu'écrire dans un flux. Seule la dé-sérialisation demande réellement du travail.
Que veux-tu sérialiser ? Nombre de type connu à la compilation ? (Il me semble que la réponse est dans les pages précédentes mais pas retrouvé)
Comment voudrais-tu idéalement utiliser la classe de sérialisation ?
Pourquoi ne pas utilisé boost::Archive ? Si c'est pars ce que tu ne sais pas comment ça fonctionne, ce n'est pas une raison.
Non si je ne veux pas utiliser boost c'est parce que j'ai eu des unregistered derived class exception, et ce même en enregistrant les classes, boost marche très bien à partir du moment ou la hiérarchie se limite à une classe A qui hérite d'une classe B.
Mais si j'ai une classe abstraite (B) qui hérite d'une classe abstraite (A) et une classe C qui hérite de la classe abstraite A, j'ai une archive excpetion.
Avec ce système j'arrive à sérializer et à désérializer sans problème, et en effet oui c'est l'entité qui devrait connaitre sont type et pas le sérializer qui doit connaître le type réel de l'entité.
Je pense que je vais donc laissé le code source comme ça.
Mais il est vrai que la sérialization est simple, c'est plutôt la désérialisation qui va poser problème.
Car pour le moment je n'ai sérializer que deux string d'une classe de base et d'une classe dérivée.
Mais j'imagine que avec les pointeurs et les tableaux ça ne doit pas être si simple. (et lorsque on a des données de différent type)
Je me demande si istream peut lire un string, le stocker dans une variable et ensuite lire un int sans connaître la taille du string...
Et pour les archives binaire je n'ose même pas imaginer.
Te rends-tu compte que ceci n’a aucun sens, ni en C++ ni dans aucun langage objet ?
La relation d’héritage public est une relation « est-un », au sens si B hérite de A, alors B est un A. C’est une relation à sens unique.
Une relation d’héritage à double sens, ça voudrait dire qu’on a à la fois B est un A, mais aussi A est un B. Autrement dit, A et B seraient en réalité la même chose !
Oui c'est vrai. ^^
Mais bon dans mon cas A est une classe template mais bon je suppose que ça :
Et ça :Code:
1
2 Wrapper<D> : public D { };
C'est en fait la même chose. (ou bien je me trompe ?)Code:
1
2 OTextArchive : public Wrapper<OTextArvhice> { };
J'ai dû retirer le public Wrapper<OTextArchive> car les deux avaient besoin de la définition complète de la classe et faire une troisième classe :
Mais bon je ne crois pas que un wrapper aurait résolu mon problème puisque de toute façon j'aurai du connaître le type de l'archive à la compilation et je ne le connais pas.Code:class OTextArchiveWrappe : public Wrapper<OTextArchive>
Sérialization => black out!
Ce n’est pas du tout la même chose.
Dans le premier cas, tu déclares une classe template Wrapper<D> qui hérite de son paramètre template. C’est un héritage tout ce qu’il y a de plus standard.
Dans le deuxième cas, tu fais ce qu’on appelle le CRTP, tu déclares une classe qui hérite de l’instanciation d’une classe template avec elle-même comme paramètre template. Il y a d’ailleurs des conditions à respecter sur Wrapper pour que cette instanciation soit possible.
Je crois surtout que tu as besoin de reprendre ta conception tranquillement, en partant de ton besoin, en décrivant tes classes, les relations entre les différentes entités. Là tu as tordu la conception avec de la technique, en partant dans une mauvaise direction au départ, en testant plein de choses, et à mon avis le code actuel ressemble à un sac de nœuds assez inextricable (qui explique d’autant plus tes difficultés :aie: ).Citation:
J'ai du retirer le public Wrapper<OTextArchive> car les deux avaient besoin de la définition complète de la classe et faire une troisième classe :
class OTextArchiveWrappe : public Wrapper<OTextArchive>
Mais bon je ne crois pas que un wrapper aurait résolu mon problème puisque de toute façon j'aurai du connaître le type de l'archive à la compilation et je ne le connais pas.
Sérialization => black out!
sauf que pour hériter le type doit être connu.
template <typename D> class Wrapper<D> : public D {}; déclare un patron de classe:
formellement, c'est:
C'est une chose de faite.Citation:
pour tout type D, soit Wrapper<D> une classe (vide, dans mon cas), héritant publiquement de D.
Passons à la suite.
formellement, c'est:Code:class OTextArchive : public Wrapper<OTextArchive>{};
Le compilateur réagit ainsi:Citation:
Soit OTextArchive une classe héritant publiquement de Wrapper<OTextArchive>
- Tiens, une instance de Wrapper<T>: Wrapper<OTextArchive>, je ne l'ai pas encore, créons-la avant de compiler OTextArchive.
- code généré: class Wrapper<OTextArchive> : public OTextArchive{};
- arg!, Je ne connais aps encore OTextArchive.
En fait, tu as:
OTextArchive hérite de Wrapper<OTextArchive> qui hérite de OTextArchive.
class OTextArchive : public Wrapper<OTextArchive> est du CRTP classique.
Par contre, l'autre est un usage étrange:
une série de classe, qui hérite chacune de quelque chose de différent.
Et je n'ose pas imaginer Wrapper<int> :aie:
Cela dit, je ne comprends pas pourquoi ton wrapper devrait hériter de la classe dérivée.
Il devrait hériter de la classe de base et déléguer à un membre du type wrappé.
Le wrapping est normalement créé par composition.
Ha ok je vois plus claire là, merci. :)