Bonjour,
Je dois manipuler un ensemble d'objets. Tous ces objets ont en commun un ensemble d'attributs et d'opérations (disons E1). De plus d'autres ensembles d'attributs et opérations (appelons les F1,...,Fn) sont communs à certains des objets manipulés (mais pas à tous). Enfin, certaines des opérations de F1,...,Fn utilisent les attributs de E1. Pour implémenter ça, je voudrai utiliser des "classes de bases virtuelles". Un petit bout de code pour fixer les idées :
Voilà donc mes questions :
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 #include <iostream> using namespace std; //------------------------------------------------------------------------ class Commun { protected: int att_E; public: Commun(int _att_E) : att_E(_att_E) {} void op_E() { cout << att_E << endl; } }; //------------------------------------------------------------------------ class Partiel1 : virtual public Commun { protected: int att_F1; public: Partiel1(int _att_F1) : Commun(0), att_F1(_att_F1) {} void op_F1() { cout << att_E << " " << att_F1 << endl; } }; //------------------------------------------------------------------------ class Partiel2 : virtual public Commun { protected: int att_F2; }; //------------------------------------------------------------------------ class A : public Partiel1 { public: A(int _att_E, int _att_F1) : Commun(2*_att_E), Partiel1(_att_F1) {} }; //------------------------------------------------------------------------ class B : public Partiel1, public Partiel2 { }; //------------------------------------------------------------------------ class SubA : public A { public: SubA(int _att_E, int _att_F1) : Commun(_att_E), A(_att_E, _att_F1) {} }; //------------------------------------------------------------------------ int main(int argc, char* argv[]) { A a(123, 456); a.op_E(); a.op_F1(); // -> Affiche : // 246 // 246 456 SubA sa(314, 271); sa.op_E(); sa.op_F1(); // -> Affiche : // 314 // 314 271 return 0; }
1) Pourquoi suis-je obligé d'appeler le constructeur de "Commun" dans la liste d'initialisation de "A" (si je ne le fais pas, ça compile pas et, normalement, on n'a le droit que d'appeler les constructeurs des classes juste au dessus dans la hiérarchie)
2) En ajoutant quelques messages de debug dans les constructeurs, je me rends compte que le constructeur de "Commun" n'est appelé qu'une seule fois : cela veut-il dire que l'appel de ce constructeur ("Commun(0)") dans la liste d'initialisation de "Partiel1" est ignoré ?
3) Y'a-t-il un moyen d'éliminer l'espèce de redondance dans la liste d'initialisation de "SubA" : pourquoi devoir transmettre 2 fois _att_E puisque l'initialisation de "Commun" semble être ignorée dans le constructeur de "A" (en effet, sa->opE() affiche 314 et non pas 624) ?
4) Existe-t-il une autre solution pour implémenter mon problème ? Bref, est-il possible de faire sans héritage virtuel ?
5) Connaissez-vous une bonne documentation sur les classes virtuelles (les facs, les bouquins et les tutos sont très bavards à propos des méthodes virtuelles, des classes abstraites mais il n'y a jamais grand chose sur les classes virtuelles, y compris dans le Stroustrup !)
Merci.
Partager