Bonjour à tous et merci par avance de vous intéresser à mon problème
Dans mon optique de lire des fichiers définissant des objets se référençant entre eux, il m'arrive fréquemment d'avoir à créer un objet avant de connaître effectivement son type. Celui-ci ne sera connu que plus tard, lors de la définition de l'objet.
Je m'explique.
Admettons que j'aie l'architecture objet suivante :
Je lis ensuite des fichiers XML "peuplant" ce modèle de données et ayant la forme :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 class Base{ //definition } class A : public Base{ //definition } class C{ public: Base* a; int attr; }
Bien sûr, il pourrait exister n'importe quel nombre de référence vers l'instance d'id "ID_A".
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 <C id="ID_C"> <!-- instance d'objet de classe "C" et d'id "ID_C" --> <C.attr>4</C.attr> <C.a ref_id="ID_A"> <!-- l'objet référencé n'existe pas encore ! --> </C> <A id="ID_A"> <!-- instance d'objet de classe "A" et d'id "ID_A" --> </A>
Le problème est relativement simple. Il existe deux cas :
- Contrairement à mon exemple, un objet "A" peut avoir été instancié avant d'être référencé par une autre instance "C", auquel cas il n'y a pas de difficulté puisqu'il me suffit de récupérer l'instance créée "A" et de la lier avec l'instance "C" :
- Ou bien comme dans mon exemple, un objet peut être référencé avant d'être instancié. Si "C" avait eu un attribut de type "A" et non de type "Base", il n'y aurait pas eu de problème puisque j'aurais pu créer un objet de type "A" d'id "ID_A" vide à la lecture de la définition de l'objet de type "C" d'id "ID_C" puis le setter correctement à la lecture de sa définition :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 A* a= getAById("ID_A"); C.a = a;
Dans le cas qui m'intéresse, l'objet référencé est en fait un objet dérivé, que je ne peux donc pas créer s'il n'existe pas encore pour le setter à postériori puisque je ne sais pas quelle classe dérivée sera choisie. Pour reprendre l'exemple précédent, ce code est clairement faux :
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 // A la lecture de "C" : // L'objet de type "A" d'id "ID_A" a-t-il déjà été référencé ? A* a = getAById("ID_A"); if(a == NULL){ a = new A; addIdA("ID_A", a); } C.a = a; // A la lecture de "A" : A* a = getAById("ID_A"); // setter "a" correctement, tous les objets ayant une référence vers "a" auront ainsi la bonne version.
Et là ça pète forcément.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 // A la lecture de "C" : // L'objet de type "Base" d'id "ID_A" a-t-il déjà été référencé ? Base* base = getBaseById("ID_A"); if(base == NULL){ base = new Base; addIdBase("ID_A", base); } C.a = base; // A la lecture de "A" : A* a = getAById("ID_A"); //en admettant que cette fonction me renvoie effectivement le bon objet, mais forcément de type réel "Base"
Comment faire pour que "C" garde sa référence vers "a" qu'il considère comme un objet de type "Base" mais qui est en fait de type "A" afin de le setter correctement à posteriori ? Le but étant bien sûr de ne faire qu'une passe et faire un minimum de calcul (c'est-à-dire ne pas reparcourir tous les objets référençant l'objet d'id "ID_A" pour mettre à jour la référence). Je ne sais pas trop comment faire pour indiquer dès la rencontre de "C" l'endroit où sera ensuite défini l'objet de type "Base" et de type réel "A" ou autre ...
Merci beaucoup pour votre aide.
Partager