Dans une application que je développe, je lis dans une table d'une base de données le nom de la classe que je dois instancier.
En clair, le nom de la classe est contenu dans une variable. Comment puis-je faire alors pour créer un objet de ce type ?
Exemple :
myvar = "MaClasse";
MaClasse *mc = new ??? <== Que dois je mettre ici pour réaliser l'instanciation ?
Merci de votre aide.
Globalement, tu ne peux pas.
C++ n'a pas de proprietes de reflexivite, a l'instar d'autres langages...
Il y a des tonnes de solutions (le pattern souvent appele "constructeur virtuel") mais tu vas avoir du boulot.
Tu peux toujours aller fouiller dans Boost, il y a certainement moult outils pour te simplifier tes problemes de serialisation.
Falk Tannhäuser
NDLCDUV schrieb:
Dans une application que je développe, je lis dans une table d'une base de données le nom de la classe que je dois instancier.
En clair, le nom de la classe est contenu dans une variable. Comment puis-je faire alors pour créer un objet de ce type ?
Exemple :
myvar = "MaClasse";
MaClasse *mc = new ??? <== Que dois je mettre ici pour réaliser l'instanciation ?
Si toutes ces classes dérivent d'une classe de base commune (disons BaseClass), tu peux faire tout simplement :
BaseClass* Create(std::string const& name) { if (name == "BaseClass") return new BaseClass; else if(name == "MaPremiereClasse") return new MaPremiereClasse; else if(name == "MaSecondeClasse" ) return new MaSecondeClasse; // etc ... else return 0; // Si le nom est inconnu (éventuellement traitement d'erreur ici ?) }
Si le nombre de classes est un peu plus important, des schémas plus sophistiqués peuvent être envisagés : _________________________________________________________________________________
class BaseClass { public: virtual ~BaseClass() {} };
class MyFirstClass : public BaseClass {}; class MySecondClass : public BaseClass {};
Idéalement le factory_map, le CallNew(), le Create() et l'initialisation seront encapsulés dans une classe Factory instanciée en singleton, éventuellement "templatisée" avec BaseClass comme paramètre template...
Falk
NDLCDUV schrieb:
Dans une application que je développe, je lis dans une table d'une base
de données le nom de la classe que je dois instancier.
En clair, le nom de la classe est contenu dans une variable. Comment
puis-je faire alors pour créer un objet de ce type ?
Exemple :
myvar = "MaClasse";
MaClasse *mc = new ??? <== Que dois je mettre ici pour réaliser
l'instanciation ?
Si toutes ces classes dérivent d'une classe de base commune (disons BaseClass), tu peux faire tout simplement :
BaseClass* Create(std::string const& name)
{
if (name == "BaseClass") return new BaseClass;
else if(name == "MaPremiereClasse") return new MaPremiereClasse;
else if(name == "MaSecondeClasse" ) return new MaSecondeClasse;
// etc ...
else return 0; // Si le nom est inconnu (éventuellement traitement d'erreur ici ?)
}
Si le nombre de classes est un peu plus important, des schémas plus sophistiqués peuvent être envisagés :
_________________________________________________________________________________
class BaseClass
{
public:
virtual ~BaseClass() {}
};
class MyFirstClass : public BaseClass {};
class MySecondClass : public BaseClass {};
Idéalement le factory_map, le CallNew(), le Create() et l'initialisation seront encapsulés dans une classe Factory instanciée en
singleton, éventuellement "templatisée" avec BaseClass comme paramètre template...
Dans une application que je développe, je lis dans une table d'une base de données le nom de la classe que je dois instancier.
En clair, le nom de la classe est contenu dans une variable. Comment puis-je faire alors pour créer un objet de ce type ?
Exemple :
myvar = "MaClasse";
MaClasse *mc = new ??? <== Que dois je mettre ici pour réaliser l'instanciation ?
Si toutes ces classes dérivent d'une classe de base commune (disons BaseClass), tu peux faire tout simplement :
BaseClass* Create(std::string const& name) { if (name == "BaseClass") return new BaseClass; else if(name == "MaPremiereClasse") return new MaPremiereClasse; else if(name == "MaSecondeClasse" ) return new MaSecondeClasse; // etc ... else return 0; // Si le nom est inconnu (éventuellement traitement d'erreur ici ?) }
Si le nombre de classes est un peu plus important, des schémas plus sophistiqués peuvent être envisagés : _________________________________________________________________________________
class BaseClass { public: virtual ~BaseClass() {} };
class MyFirstClass : public BaseClass {}; class MySecondClass : public BaseClass {};
Idéalement le factory_map, le CallNew(), le Create() et l'initialisation seront encapsulés dans une classe Factory instanciée en singleton, éventuellement "templatisée" avec BaseClass comme paramètre template...
Falk
NDLCDUV
NDLCDUV a pensé très fort :
Bonjour,
Dans une application que je développe, je lis dans une table d'une base de données le nom de la classe que je dois instancier.
En clair, le nom de la classe est contenu dans une variable. Comment puis-je faire alors pour créer un objet de ce type ?
Je pensais éventuellement utiliser une simple fabrique, qui contiendrait la méthode statique suivante :
Pas besoin de dire en commentaire qu'il s'agit d'une fonction de classe. Il suffit de mettre static devant.
{ omr = NULL;
if (nomClasse == "ClasseDerivee1") omr = new ClasseDerivee1();
Ou simplement if (nomClasse == ... ) return new ClasseDerivee1();
if (nomClasse == "ClasseDerivee2") omr = new ClasseDerivee2();
return (MaClasseMere *)omr;
Pas besoin de caster et surtout pas avec un cast C.
}
mais cette solution me parait très (trop ?) simple par rapport à celles que vous me proposez. N'est ce pas pourtant une solution viable ?
Tout dépend de la quantité de couplage que tu peux supporter. Typiquement, avec ta solution, tu devra recompiler ce fichier dès qu'une des classes sera modifiée et il te faudra maintenir ta liste de classe.
Avec un simple système d'enregistrement, tu t'évites ce genre de désagrément. Et le cout est relativement faible (sauf si tu as besoin d'appeler ta factory avant d'entrer dans le main()).
-- Michael
NDLCDUV wrote:
NDLCDUV a pensé très fort :
Bonjour,
Dans une application que je développe, je lis dans une table d'une
base de données le nom de la classe que je dois instancier.
En clair, le nom de la classe est contenu dans une variable. Comment
puis-je faire alors pour créer un objet de ce type ?
Je pensais éventuellement utiliser une simple fabrique, qui contiendrait
la méthode statique suivante :
Pas besoin de dire en commentaire qu'il s'agit d'une fonction de classe.
Il suffit de mettre static devant.
{
omr = NULL;
if (nomClasse == "ClasseDerivee1")
omr = new ClasseDerivee1();
Ou simplement
if (nomClasse == ... ) return new ClasseDerivee1();
if (nomClasse == "ClasseDerivee2")
omr = new ClasseDerivee2();
return (MaClasseMere *)omr;
Pas besoin de caster et surtout pas avec un cast C.
}
mais cette solution me parait très (trop ?) simple par rapport à celles
que vous me proposez. N'est ce pas pourtant une solution viable ?
Tout dépend de la quantité de couplage que tu peux supporter.
Typiquement, avec ta solution, tu devra recompiler ce fichier dès qu'une
des classes sera modifiée et il te faudra maintenir ta liste de classe.
Avec un simple système d'enregistrement, tu t'évites ce genre de
désagrément. Et le cout est relativement faible (sauf si tu as besoin
d'appeler ta factory avant d'entrer dans le main()).
Pas besoin de dire en commentaire qu'il s'agit d'une fonction de classe. Il suffit de mettre static devant.
{ omr = NULL;
if (nomClasse == "ClasseDerivee1") omr = new ClasseDerivee1();
Ou simplement if (nomClasse == ... ) return new ClasseDerivee1();
if (nomClasse == "ClasseDerivee2") omr = new ClasseDerivee2();
return (MaClasseMere *)omr;
Pas besoin de caster et surtout pas avec un cast C.
}
mais cette solution me parait très (trop ?) simple par rapport à celles que vous me proposez. N'est ce pas pourtant une solution viable ?
Tout dépend de la quantité de couplage que tu peux supporter. Typiquement, avec ta solution, tu devra recompiler ce fichier dès qu'une des classes sera modifiée et il te faudra maintenir ta liste de classe.
Avec un simple système d'enregistrement, tu t'évites ce genre de désagrément. Et le cout est relativement faible (sauf si tu as besoin d'appeler ta factory avant d'entrer dans le main()).
-- Michael
David Fleury
Marc Espie a écrit :
Globalement, tu ne peux pas.
C++ n'a pas de proprietes de reflexivite, a l'instar d'autres langages...
J'ai l'impression que tu exprimes un regret ici. Du coup "à l'instar" (comme) fait bizarre ici Mais si c'était pas l'idée alors désolé. Je me rendors :)
Mais ce n'est pas vraiment du C++ ;)
David
Marc Espie a écrit :
Globalement, tu ne peux pas.
C++ n'a pas de proprietes de reflexivite, a l'instar d'autres langages...
J'ai l'impression que tu exprimes un regret ici.
Du coup "à l'instar" (comme) fait bizarre ici
Mais si c'était pas l'idée alors désolé. Je me rendors :)
C++ n'a pas de proprietes de reflexivite, a l'instar d'autres langages...
J'ai l'impression que tu exprimes un regret ici. Du coup "à l'instar" (comme) fait bizarre ici Mais si c'était pas l'idée alors désolé. Je me rendors :)
Mais ce n'est pas vraiment du C++ ;)
David
espie
In article <49d3b7ca$0$5262$, David Fleury wrote:
Marc Espie a écrit :
Globalement, tu ne peux pas.
C++ n'a pas de proprietes de reflexivite, a l'instar d'autres langages...
J'ai l'impression que tu exprimes un regret ici. Du coup "à l'instar" (comme) fait bizarre ici Mais si c'était pas l'idée alors désolé. Je me rendors :)
Non, pas vraiment de regret. Tu ne peux pas non plus faire de prolog en C++, et ca n'est pas vraiment grave. Ca pousse juste les gens a developper d'autres solutions, qui souvent fonctionnent "mieux" dans le contexte.
Mais ce n'est pas vraiment du C++ ;)
J'ai l'impression que le posteur initial voulait une technique equivalente a ce qui est pratique en java.
In article <49d3b7ca$0$5262$426a34cc@news.free.fr>,
David Fleury <dfleury2@libertysurf.fr> wrote:
Marc Espie a écrit :
Globalement, tu ne peux pas.
C++ n'a pas de proprietes de reflexivite, a l'instar d'autres langages...
J'ai l'impression que tu exprimes un regret ici.
Du coup "à l'instar" (comme) fait bizarre ici
Mais si c'était pas l'idée alors désolé. Je me rendors :)
Non, pas vraiment de regret. Tu ne peux pas non plus faire de prolog
en C++, et ca n'est pas vraiment grave. Ca pousse juste les gens a developper
d'autres solutions, qui souvent fonctionnent "mieux" dans le contexte.
Mais ce n'est pas vraiment du C++ ;)
J'ai l'impression que le posteur initial voulait une technique equivalente
a ce qui est pratique en java.
C++ n'a pas de proprietes de reflexivite, a l'instar d'autres langages...
J'ai l'impression que tu exprimes un regret ici. Du coup "à l'instar" (comme) fait bizarre ici Mais si c'était pas l'idée alors désolé. Je me rendors :)
Non, pas vraiment de regret. Tu ne peux pas non plus faire de prolog en C++, et ca n'est pas vraiment grave. Ca pousse juste les gens a developper d'autres solutions, qui souvent fonctionnent "mieux" dans le contexte.
Mais ce n'est pas vraiment du C++ ;)
J'ai l'impression que le posteur initial voulait une technique equivalente a ce qui est pratique en java.
Sylvain SF
Marc Espie a écrit :
J'ai l'impression que le posteur initial voulait une technique equivalente a ce qui est pratique en java.
dans sa question initiale oui, à tout le moins cela pouvait faire "regretter" la réflexivité Java; dans son exemple posté plus tard, beaucoup moins.
btw, Objective-C permettrait cela non ?
SF.
Marc Espie a écrit :
J'ai l'impression que le posteur initial voulait une technique equivalente
a ce qui est pratique en java.
dans sa question initiale oui, à tout le moins cela pouvait
faire "regretter" la réflexivité Java; dans son exemple posté
plus tard, beaucoup moins.