Salut.
j'essaye de simplifier mon système de sérialisation d'objet, avec le polymorphisme je devais en effet déclarer une classe de base qui prenait un template ce qui était plutôt gênant lorsque je voulais stocker mes objets dans un conteneur et les sérialiser car après je devais rechercher le type et faire un cast.
De plus comme la fonction serialize prend un paramètre template je ne peut pas faire une interface, de plus ce paramètre template possède des fonctions qui sont elle même template donc je ne peux pas faire de classe de base non plus.
L'idée est de faire une classe de base contenant, tout les type des classes dérivée à l'aide d'un template variadique, et de rechercher le bon type à l'aide d'un tuple, comme ceci :
Code cpp : 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 #ifndef ODFAEG_SERIALIZATION #define ODFAEG_SERIALIZATION #include "archive.h" #include <iostream> #include <typeinfo> #include "tuple.h" #include <tuple> namespace odfaeg { template <class B, class... D> class Serializer { public : Serializer (D... derived) { derivedClasses = std::forward_as_tuple(derived...); baseObject = nullptr; } Serializer(B* baseObject, D... derived) : baseObject(baseObject) { derivedClasses = std::forward_as_tuple(derived...); } template <typename Archive> void checkType(Archive & ar) { serialize(derivedClasses, ar); } template<int... S, typename Archive> void serialize (std::tuple<D...> types, Archive & ar) { //The class doesn't inherits; if (sizeof...(D) == 0 && baseObject != nullptr) { baseObject->serialize(ar); //The base class is abstract and have derived classes. (We must check the type of the derived object at runtime. } else if (sizeof...(D) > 0 && baseObject == nullptr) { serialize(typename helper::gens<sizeof...(D)>::type(), types, ar); //The base class isn't abstract and have derived classes. } else if (sizeof...(D) > 0 && baseObject != nullptr) { if(!serialize(typename helper::gens<sizeof...(D)>::type(), types, ar)) baseObject->serialize(ar); } } template<int... S, typename Archive> bool serialize(helper::seq<S...>, std::tuple<D...> params, Archive & ar) { if (evaluateType(std::get<S>(params)..., ar)) { return true; } return false; } template <typename T, typename Archive> bool evaluateType (T type, Archive & ar) { if (typeid(type) == typeid(*baseObject)) { type.serialize(ar); return true; } } virtual void onSave() { } virtual void onLoad() { } B* baseObject; std::tuple<D...> derivedClasses; }; } #endif // SERIALIZATION
Malheureusement ceci n'améliore pas vraiment mon problème, je ne peux pas faire hérité ObjetToutBete de Serializer<ObjetToutBete, ObjetContenantObjetToutBete> car, la classe Serializer à besoin de la définition complète de la classe ObjetContenantObjetToutBete, et même chose dans l'autre sens, la classe ObjetContenantObjetToutBete à besoin de la définition complète de la classe ObjetToutBete de ce fait je ne peux pas non plus déclarer la classe ObjetContenantObjetToutBete avant la classe ObjetToutBete.
J'ai du donc créer un troisième classe que voici, celle-ci contient juste le type réel de l'objet, ainsi que les types dérivé, et l'objet à sérializer.
Code cpp : 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 class ObjetToutBete { public : ObjetToutBete() {} ObjetToutBete(std::string name) { this->name = name; id = new int(5); } template <typename Archive> void serialize(Archive & ar) { ar(name); ar(id); } int* getId() { return id; } //Pour que typeid marche!!! virtual void foo() {} private : std::string name; int* id; }; class ObjetContenantObjetToutBete : public ObjetToutBete { public : ObjetContenantObjetToutBete () {} ObjetContenantObjetToutBete(std::string name) : ObjetToutBete("un objet tout bête.") { this->name = name; id = ObjetToutBete::getId(); } template <typename Archive> void serialize(Archive & ar) { ObjetToutBete::serialize(ar); ar(name); ar(id); } private : int* id; std::string name; }; class SerializableObject : public odfaeg::Serializer<ObjetToutBete, ObjetContenantObjetToutBete> { public : SerializableObject(ObjetToutBete* objet) : Serializer<ObjetToutBete, ObjetContenantObjetToutBete>(objet, static_cast<ObjetContenantObjetToutBete&>(*objet)) { } };
L'inconvénient est que je dois créer un nouvelle classe pour chacune des classes de base qui ont des classes dérivée ce qui est un peu lourd;
Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 ObjetToutBete* ocotb = new ObjetContenantObjetToutBete("Objet contenant objet tout bête."); SerializableObject so(ocotb);
Et j'aimerais pouvoir simplifier tout ça à l'aide d'une macro afin qu'il ne soit plus nécessaire de créer manuellement la classe supplémentaire.
Voilà merci de votre aide.
Partager