Je dois réaliser une sorte de mini-interpréteur (dans le cadre d'un projet
plus gros), j'ai refléchi sérieusement à la manière de l'implémenter et ai
commencé à coder. J'ai défini toute mes classes/interfaces mais voila que
je bloque lors du codage de la fonction centrale... J'y avais songé avant
pourtant et j'avais pensé que ce serait plus simple.
Donc voici mon problème dans une situation simplifiée :
J'ai une classe de base Object dont hérite plusieurs classes : String,
Int, ... et j'ai une std::string qui contient le nom d'une de ces classes.
Je voudrais allouer une instance d'une classe (héritant de Object) dont le
nom est contenu dans ma chaine :
Evidemment je ne peux pas utiliser les templates vu que ca doit etre
dynamique, je ne peux pas non plus faire un switch géant avec des valeurs
rtti (ou autre) puisque il y a un nombre de classe potentiellement
illimité :)
J'ai pensé aussi (même si c'est stupide) à faire un new Object() puis faire
un casting vers Int() ou String() mais c'est pareil je ne connais pas le
type à l'avance pour mon casting.
Ensuite comment appeler les fonctions membres ? La je pensais résoudre le
problème avec un map contenant nom_de_la_fonction <->
pointeur_vers_la_fonction qui serait initialisé dans mes classes héritants
de Object. Ce tableau pourrait être initialisé dans le constructeur, et je
pourrais avoir une fonction virtuelle de Object comme ca : void *
getFunctionPtr(std::string functionName)...
En fait c'est surtout l'allocation qui va pas. Je cherche le moyen de
pouvoir trimballer un type comme le fait l'opérateur sizeof ou les macros
va_* mais je ne sais pas si c'est réaliste.
Donc si vous avez une idée ou un lien ca serait sympa :)
Un petit problème ici : si j'ai bien compris, "new_magique()" renvoie un pointeur vers un objet d'une classe dérivée de Object.
Il y a donc conversion (pointeur vers un objet "dérivé") -> (ptr vers un objet "de base") Cette conversion est automatique : return new_magique(str);
dynamic_cast<> est utile dans l'autre sens :
Base* ptrB= new Derivee; Derivee* ptrD= dynamic_cast<Derivee*> (ptrB);
Evidemment je ne peux pas utiliser les templates vu que ca doit etre dynamique, je ne peux pas non plus faire un switch géant avec des valeurs rtti (ou autre) puisque il y a un nombre de classe potentiellement illimité :)
[Note en passant : boost::any peut peut-être t'aider ?]
De toutes façons, il faut que chaque classe soit "enregistrée" dans une liste quelconque.
class EnregistreClasse { public: EnregistreClasse (CreateurDObject fonction_creation, std::string const &nom); /* Ce pseudo-constructeur a pour mission de créer "ptr_map_createurs" si ce n'est déjà fait, puis (*ptr_map_createurs)[nom]= fonction_creation; */ };
#define MACRO_ENREGISTRE_CLASSE( nom_classe) Object* Createur##nom_classe() { return new nom_classe; }
Un petit problème ici : si j'ai bien compris, "new_magique()" renvoie
un pointeur vers un objet d'une classe dérivée de Object.
Il y a donc conversion
(pointeur vers un objet "dérivé") -> (ptr vers un objet "de base")
Cette conversion est automatique :
return new_magique(str);
dynamic_cast<> est utile dans l'autre sens :
Base* ptrB= new Derivee;
Derivee* ptrD= dynamic_cast<Derivee*> (ptrB);
Evidemment je ne peux pas utiliser les templates vu que ca doit etre
dynamique, je ne peux pas non plus faire un switch géant avec des valeurs
rtti (ou autre) puisque il y a un nombre de classe potentiellement
illimité :)
[Note en passant : boost::any peut peut-être t'aider ?]
De toutes façons, il faut que chaque classe soit "enregistrée" dans
une liste quelconque.
class EnregistreClasse
{
public:
EnregistreClasse (CreateurDObject fonction_creation,
std::string const &nom);
/* Ce pseudo-constructeur a pour mission de créer
"ptr_map_createurs" si ce n'est déjà fait, puis
(*ptr_map_createurs)[nom]= fonction_creation;
*/
};
#define MACRO_ENREGISTRE_CLASSE( nom_classe)
Object* Createur##nom_classe()
{
return new nom_classe;
}
Un petit problème ici : si j'ai bien compris, "new_magique()" renvoie un pointeur vers un objet d'une classe dérivée de Object.
Il y a donc conversion (pointeur vers un objet "dérivé") -> (ptr vers un objet "de base") Cette conversion est automatique : return new_magique(str);
dynamic_cast<> est utile dans l'autre sens :
Base* ptrB= new Derivee; Derivee* ptrD= dynamic_cast<Derivee*> (ptrB);
Evidemment je ne peux pas utiliser les templates vu que ca doit etre dynamique, je ne peux pas non plus faire un switch géant avec des valeurs rtti (ou autre) puisque il y a un nombre de classe potentiellement illimité :)
[Note en passant : boost::any peut peut-être t'aider ?]
De toutes façons, il faut que chaque classe soit "enregistrée" dans une liste quelconque.
class EnregistreClasse { public: EnregistreClasse (CreateurDObject fonction_creation, std::string const &nom); /* Ce pseudo-constructeur a pour mission de créer "ptr_map_createurs" si ce n'est déjà fait, puis (*ptr_map_createurs)[nom]= fonction_creation; */ };
#define MACRO_ENREGISTRE_CLASSE( nom_classe) Object* Createur##nom_classe() { return new nom_classe; }
De toutes façons, il faut que chaque classe soit "enregistrée" dans une liste quelconque.
Note : tout ce qui suit cette phrase est très probablement des élucubrations d'un esprit fatigué, postées dans le seul but de faire hurler ceux qui savent faire ça proprement (et/ou ont lu "Design Patterns").
Enfin bref, à prendre avec des pincettes.
De toutes façons, il faut que chaque classe soit "enregistrée" dans
une liste quelconque.
Note : tout ce qui suit cette phrase est très probablement des
élucubrations d'un esprit fatigué, postées dans le seul but de faire
hurler ceux qui savent faire ça proprement (et/ou ont lu "Design
Patterns").
De toutes façons, il faut que chaque classe soit "enregistrée" dans une liste quelconque.
Note : tout ce qui suit cette phrase est très probablement des élucubrations d'un esprit fatigué, postées dans le seul but de faire hurler ceux qui savent faire ça proprement (et/ou ont lu "Design Patterns").
Enfin bref, à prendre avec des pincettes.
Fabien LE LEZ
On Sat, 13 Aug 2005 16:29:36 +0200, Fabien LE LEZ :
static std::map <std::string, Object
"CreateurDObject", ici, bien sûr.
* ptr_map_createurs= 0;
Bien évidemment, il ne faut jamais écrire ça, mais plutôt :
De toutes façons, il faut que chaque classe soit "enregistrée" dans une liste quelconque.
J'avais bien pensé à enregistrer les classes dans une liste mais je ne voyais pas comment ! Là l'idée de stocker des pointeurs de fonction n'est vraiment pas mal ! Donc je prend, merci beaucoup !
-- nico
Salut,
De toutes façons, il faut que chaque classe soit "enregistrée" dans
une liste quelconque.
J'avais bien pensé à enregistrer les classes dans une liste mais je ne
voyais pas comment ! Là l'idée de stocker des pointeurs de fonction n'est
vraiment pas mal ! Donc je prend, merci beaucoup !
De toutes façons, il faut que chaque classe soit "enregistrée" dans une liste quelconque.
J'avais bien pensé à enregistrer les classes dans une liste mais je ne voyais pas comment ! Là l'idée de stocker des pointeurs de fonction n'est vraiment pas mal ! Donc je prend, merci beaucoup !
-- nico
Fabien LE LEZ
On Sat, 13 Aug 2005 16:29:36 +0200, Fabien LE LEZ :
(Createur##nom_classe, nom_classe)
Tiens, encore une erreur... Il faut écrire :
(Createur##nom_classe, #nom_classe)
On Sat, 13 Aug 2005 16:29:36 +0200, Fabien LE LEZ
<gramster@gramster.com>:
On Sat, 13 Aug 2005 16:29:36 +0200, Fabien LE LEZ :
(Createur##nom_classe, nom_classe)
Tiens, encore une erreur... Il faut écrire :
(Createur##nom_classe, #nom_classe)
Arnaud Meurgues
nico wrote:
J'avais bien pensé à enregistrer les classes dans une liste mais je ne voyais pas comment ! Là l'idée de stocker des pointeurs de fonction n'est vraiment pas mal ! Donc je prend, merci beaucoup !
Autre possibilité : si Object a une fonction virtuelle clone(), on peut enregistrer des instances directement et utiliser clone() pour produire une nouvelle instance.
-- Arnaud
nico wrote:
J'avais bien pensé à enregistrer les classes dans une liste mais je ne
voyais pas comment ! Là l'idée de stocker des pointeurs de fonction n'est
vraiment pas mal ! Donc je prend, merci beaucoup !
Autre possibilité : si Object a une fonction virtuelle clone(), on peut
enregistrer des instances directement et utiliser clone() pour produire
une nouvelle instance.
J'avais bien pensé à enregistrer les classes dans une liste mais je ne voyais pas comment ! Là l'idée de stocker des pointeurs de fonction n'est vraiment pas mal ! Donc je prend, merci beaucoup !
Autre possibilité : si Object a une fonction virtuelle clone(), on peut enregistrer des instances directement et utiliser clone() pour produire une nouvelle instance.