Probleme de conception sur heritage virtuel et template
Bonjour, j'ai une question de base sur le couplage heritage virtuel/ template qui m'embete depuis un moment. Je l'expose sur un cas tres simple, et sans aucun interet pratique.
Pour le mariage, c'est le tric standard "TypeErasure" si je ne m'abuse. Mmmm j'ai feuillete le tuto de Alp Mestan "Mariage de la Programmation Orientee Objet et de la Programmation Generique: TypeErasure".
Bon, donc je pars une classe de base "Object" implementant une fonction virtuelle pure, disons "fonction". Puis je derive une classe template "ObjectImplemented" a un parametre. Cette classe est juste un "squelette" en ce sens qu'elle ne doit jamais etre instanciee. Elle ne sert que de base pour ecrire N classes specialisees.
Cela etant, je cree ensuite une classe "CompositeObject" ayant pour membre un vector<Object*> nomme "liste" disons. Mon probleme est alors du "genre": je veux construire un constructeur par copie (disons qu'il prenne en parametre "liste_source"). Bon, clairement j'expose le probleme sur le cas du constructeur par copie mais il survient dans beaucoup d'autres types d'operations... Pour le regler, je n'ai rien trouver de mieux que de proceder ainsi:
- la classe de base "Object" possede un membre "int type"
- chaque classe specialisee "ObjectImplemented<T>" definit "type" de maniere univoque
- pour chaque element de "liste_source", je teste son type et en fonction, i.e dans un if, je fais un new sur la classe template specialisee associee.
Bon, mon probleme c'est que dans mes implementations concretes, le nombre de specialisationest tres grand (genre 100) et je dois donc me taper
une sorte de "if(type==0){ new ObjectImplemented<T0> }else if(type==1000) {new ObjectImplemented<T100>" geant ce qui est tres long et penible....
Bon, je pense que je ne procede pas du tout de la bonne maniere donc si vous pouviez m'indiquer la demarche standard pour ce genre de souci ca serait cool... Je pense a definir une fonction virtuelle d'instanciation dans "Object", fonction que j'implemente concretement dans mes classes derivees specialisees (cf. section "CECI EST UNE AUTRE IDEE" dans le code ci-dessous). Est-ce bon?
Ci-dessous, je joins un code source :
Code:
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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
| //-----------------------------------------------------------------------------
//Classe de base, virtuelle pure
//-----------------------------------------------------------------------------
class Object
{
public:
virtual void fonction() = 0;
//Pour garder trace des enfants implementant la classe:
static int type = 0;
//CECI EST UNE AUTRE IDEE:
virtual bool instancie(Object* source) = 0;
};
//-----------------------------------------------------------------------------
//Classe derivee template. Sert juste de "squelette" pour specialisation.
//-----------------------------------------------------------------------------
template<int T>
class ObjectImplemented : public Object
{
public:
//Mum, bon ca aussi je ne suis pas sur que ce soit tres "professionnel"
//Comment je peux faire plus correctement???
ObjectImplemented()
{
cout << "FATAL: this class should never be instancied" << endl;
exit(1);
}
};
//-----------------------------------------------------------------------------
//Specialisation effective 1. Implemente la virtualite.
//-----------------------------------------------------------------------------
template<>
class ObjectImplemented<1> : public Object
{
public:
ObjectImplemented()
{
//Definit <type>
type=1;
}
void fonction()
{
//Bla, bla, bla...
cout << "Je suis T1" << endl;
}
//CECI EST UNE AUTRE IDEE:
bool instancie(Object* source)
{
if(source==0)
{
source = new ObjectImplemented<2>();
return true;
}
else
{
return false;
}
}
};
//-----------------------------------------------------------------------------
//Specialisation effective 2. Implemente la virtualite.
//-----------------------------------------------------------------------------
template<>
class ObjectImplemented<2> : public Object
{
public:
ObjectImplemented()
{
//Definit <type>
type=2;
}
void fonction()
{
//Bla, bla, bla...
cout << "Je suis T2" << endl;
}
//CECI EST UNE AUTRE IDEE:
bool instancie(Object* source)
{
if(source==0)
{
source = new ObjectImplemented<2>();
return true;
}
else
{
return false;
}
}
};
//-----------------------------------------------------------------------------
//La classe composite. C'est elle qui est penible a gerer pour moi...
//-----------------------------------------------------------------------------
class CompositeObject
{
public:
//Mon vector d'object virtuel
vector<Object*> liste;
//L'exemple du constructeur de copie qui m'embete:
CompositeObject(const CompositeObject& source)
{
for(int i=0;i<source.size();i++)
{
//Cette structure "if" m'enerve, m'enerve...
if(source[i]->type==1)
{
Object* object_aux = new ObjectImplemented<1>();
liste.push_back(object_aux);
}
else if(source[i]->type==2)
{
Object* object_aux = new ObjectImplemented<2>();
liste.push_back(object_aux);
}
//CECI EST UNE AUTRE IDEE:
Object* object_aux = 0;
source[i]->instancie(object_aux);
}
}
}; |
Bon, en esperant que j'aurais une ou deux reponses, ou au moins des liens pour me debrouiller, merci d'avance.