Bonjour a tous,
J'ai un petit probleme de conception et j'espere que quelqu'un aura
quelques idees à proposer.
J'ai une fabrique qui sert a creer des instances de classes qui sont
toutes derivées de la meme classe de base.
Ainsi ma classe ressemble a ce qui suit:
class Fabrique
{
typedef Base* (CREATE_FUNC)();
std::map<std::string,CREATE_FUNC> creators;
....
public:
Base* createObject(std::string objectName)
};
où createObject va utiliser la fonction enregistrée dans la map pour
creer l'objet.
J'aimerais que les classes, derivant de Object, que je declare
s'enregistre automatiquement dans la fabrique.
Le moyen que je pense utiliser est de faire en sorte que la fabrique
soit un singleton et dans le .cpp d'avoir un code du genre:
/// ObjectN.h
class ObjectN : public Object
{
};
/// ObjectN.cpp
#include "Fabrique.h"
#include "ObjectN.h"
Base* Create() { return static_cast<Base*>(new ObjectN); }
int ObjectN::d = Fabrique::getInstance()->register("ObjectN",Create);
(d est static dans ObjectN)
Mais cette solution ne me satisfait pas vraiment, surtout parce que
je ne suis pas certain que 'register' sera appeler effectivement par
tous les compilateurs (a cause d'optimisation puisque je n'utilise
plus d apres).
Bonjour a tous,
J'ai un petit probleme de conception et j'espere que quelqu'un aura
quelques idees à proposer.
J'ai une fabrique qui sert a creer des instances de classes qui sont
toutes derivées de la meme classe de base.
Ainsi ma classe ressemble a ce qui suit:
class Fabrique
{
typedef Base* (CREATE_FUNC)();
std::map<std::string,CREATE_FUNC> creators;
....
public:
Base* createObject(std::string objectName)
};
où createObject va utiliser la fonction enregistrée dans la map pour
creer l'objet.
J'aimerais que les classes, derivant de Object, que je declare
s'enregistre automatiquement dans la fabrique.
Le moyen que je pense utiliser est de faire en sorte que la fabrique
soit un singleton et dans le .cpp d'avoir un code du genre:
/// ObjectN.h
class ObjectN : public Object
{
};
/// ObjectN.cpp
#include "Fabrique.h"
#include "ObjectN.h"
Base* Create() { return static_cast<Base*>(new ObjectN); }
int ObjectN::d = Fabrique::getInstance()->register("ObjectN",Create);
(d est static dans ObjectN)
Mais cette solution ne me satisfait pas vraiment, surtout parce que
je ne suis pas certain que 'register' sera appeler effectivement par
tous les compilateurs (a cause d'optimisation puisque je n'utilise
plus d apres).
Bonjour a tous,
J'ai un petit probleme de conception et j'espere que quelqu'un aura
quelques idees à proposer.
J'ai une fabrique qui sert a creer des instances de classes qui sont
toutes derivées de la meme classe de base.
Ainsi ma classe ressemble a ce qui suit:
class Fabrique
{
typedef Base* (CREATE_FUNC)();
std::map<std::string,CREATE_FUNC> creators;
....
public:
Base* createObject(std::string objectName)
};
où createObject va utiliser la fonction enregistrée dans la map pour
creer l'objet.
J'aimerais que les classes, derivant de Object, que je declare
s'enregistre automatiquement dans la fabrique.
Le moyen que je pense utiliser est de faire en sorte que la fabrique
soit un singleton et dans le .cpp d'avoir un code du genre:
/// ObjectN.h
class ObjectN : public Object
{
};
/// ObjectN.cpp
#include "Fabrique.h"
#include "ObjectN.h"
Base* Create() { return static_cast<Base*>(new ObjectN); }
int ObjectN::d = Fabrique::getInstance()->register("ObjectN",Create);
(d est static dans ObjectN)
Mais cette solution ne me satisfait pas vraiment, surtout parce que
je ne suis pas certain que 'register' sera appeler effectivement par
tous les compilateurs (a cause d'optimisation puisque je n'utilise
plus d apres).
/// ObjectN.cpp
#include "Fabrique.h"
#include "ObjectN.h"
Base* Create() { return static_cast<Base*>(new ObjectN); }
int ObjectN::d = Fabrique::getInstance()->register("ObjectN",Create);
(d est static dans ObjectN)
Mais cette solution ne me satisfait pas vraiment, surtout parce que
je ne suis pas certain que 'register' sera appeler effectivement par
tous les compilateurs (a cause d'optimisation puisque je n'utilise
plus d apres).
A part çà, c'est la méthode classique de faire une factory. Je ne pense pas
qu'un compilateur est le droit de zapper l'appel à register.
/// ObjectN.cpp
#include "Fabrique.h"
#include "ObjectN.h"
Base* Create() { return static_cast<Base*>(new ObjectN); }
int ObjectN::d = Fabrique::getInstance()->register("ObjectN",Create);
(d est static dans ObjectN)
Mais cette solution ne me satisfait pas vraiment, surtout parce que
je ne suis pas certain que 'register' sera appeler effectivement par
tous les compilateurs (a cause d'optimisation puisque je n'utilise
plus d apres).
A part çà, c'est la méthode classique de faire une factory. Je ne pense pas
qu'un compilateur est le droit de zapper l'appel à register.
/// ObjectN.cpp
#include "Fabrique.h"
#include "ObjectN.h"
Base* Create() { return static_cast<Base*>(new ObjectN); }
int ObjectN::d = Fabrique::getInstance()->register("ObjectN",Create);
(d est static dans ObjectN)
Mais cette solution ne me satisfait pas vraiment, surtout parce que
je ne suis pas certain que 'register' sera appeler effectivement par
tous les compilateurs (a cause d'optimisation puisque je n'utilise
plus d apres).
A part çà, c'est la méthode classique de faire une factory. Je ne pense pas
qu'un compilateur est le droit de zapper l'appel à register.
plotark wrote:J'ai un petit probleme de conception et j'espere que quelqu'un aura
quelques idees à proposer. J'ai une fabrique qui sert a creer des
instances de classes qui sont toutes derivées de la meme classe de
base.
Ainsi ma classe ressemble a ce qui suit:
class Fabrique
{
typedef Base* (CREATE_FUNC)();
std::map<std::string,CREATE_FUNC> creators;
....
public:
Base* createObject(std::string objectName)
};
où createObject va utiliser la fonction enregistrée dans la map pour
creer l'objet. J'aimerais que les classes, derivant de Object, que
je declare s'enregistre automatiquement dans la fabrique.
Le moyen que je pense utiliser est de faire en sorte que la fabrique
soit un singleton et dans le .cpp d'avoir un code du genre:
/// ObjectN.h
class ObjectN : public Object
{
};
/// ObjectN.cpp
#include "Fabrique.h"
#include "ObjectN.h"
Base* Create() { return static_cast<Base*>(new ObjectN); }
int ObjectN::d = Fabrique::getInstance()->register("ObjectN",Create);
(d est static dans ObjectN)
Mais cette solution ne me satisfait pas vraiment, surtout parce que
je ne suis pas certain que 'register' sera appeler effectivement par
tous les compilateurs (a cause d'optimisation puisque je n'utilise
plus d apres).
A quoi de sert ObjectN::d exactement, et de quel type est-il?
register ne devrait rien renvoyer et lever une exception en cas
d'erreur (de toute façon, si tes classes dérivées ne peuvent
s'enregistrer dans la factory, le mieux est d'aborter immédiatement
ton programme).
A part çà, c'est la méthode classique de faire une factory. Je ne
pense pas qu'un compilateur est le droit de zapper l'appel à register.
plotark wrote:
J'ai un petit probleme de conception et j'espere que quelqu'un aura
quelques idees à proposer. J'ai une fabrique qui sert a creer des
instances de classes qui sont toutes derivées de la meme classe de
base.
Ainsi ma classe ressemble a ce qui suit:
class Fabrique
{
typedef Base* (CREATE_FUNC)();
std::map<std::string,CREATE_FUNC> creators;
....
public:
Base* createObject(std::string objectName)
};
où createObject va utiliser la fonction enregistrée dans la map pour
creer l'objet. J'aimerais que les classes, derivant de Object, que
je declare s'enregistre automatiquement dans la fabrique.
Le moyen que je pense utiliser est de faire en sorte que la fabrique
soit un singleton et dans le .cpp d'avoir un code du genre:
/// ObjectN.h
class ObjectN : public Object
{
};
/// ObjectN.cpp
#include "Fabrique.h"
#include "ObjectN.h"
Base* Create() { return static_cast<Base*>(new ObjectN); }
int ObjectN::d = Fabrique::getInstance()->register("ObjectN",Create);
(d est static dans ObjectN)
Mais cette solution ne me satisfait pas vraiment, surtout parce que
je ne suis pas certain que 'register' sera appeler effectivement par
tous les compilateurs (a cause d'optimisation puisque je n'utilise
plus d apres).
A quoi de sert ObjectN::d exactement, et de quel type est-il?
register ne devrait rien renvoyer et lever une exception en cas
d'erreur (de toute façon, si tes classes dérivées ne peuvent
s'enregistrer dans la factory, le mieux est d'aborter immédiatement
ton programme).
A part çà, c'est la méthode classique de faire une factory. Je ne
pense pas qu'un compilateur est le droit de zapper l'appel à register.
plotark wrote:J'ai un petit probleme de conception et j'espere que quelqu'un aura
quelques idees à proposer. J'ai une fabrique qui sert a creer des
instances de classes qui sont toutes derivées de la meme classe de
base.
Ainsi ma classe ressemble a ce qui suit:
class Fabrique
{
typedef Base* (CREATE_FUNC)();
std::map<std::string,CREATE_FUNC> creators;
....
public:
Base* createObject(std::string objectName)
};
où createObject va utiliser la fonction enregistrée dans la map pour
creer l'objet. J'aimerais que les classes, derivant de Object, que
je declare s'enregistre automatiquement dans la fabrique.
Le moyen que je pense utiliser est de faire en sorte que la fabrique
soit un singleton et dans le .cpp d'avoir un code du genre:
/// ObjectN.h
class ObjectN : public Object
{
};
/// ObjectN.cpp
#include "Fabrique.h"
#include "ObjectN.h"
Base* Create() { return static_cast<Base*>(new ObjectN); }
int ObjectN::d = Fabrique::getInstance()->register("ObjectN",Create);
(d est static dans ObjectN)
Mais cette solution ne me satisfait pas vraiment, surtout parce que
je ne suis pas certain que 'register' sera appeler effectivement par
tous les compilateurs (a cause d'optimisation puisque je n'utilise
plus d apres).
A quoi de sert ObjectN::d exactement, et de quel type est-il?
register ne devrait rien renvoyer et lever une exception en cas
d'erreur (de toute façon, si tes classes dérivées ne peuvent
s'enregistrer dans la factory, le mieux est d'aborter immédiatement
ton programme).
A part çà, c'est la méthode classique de faire une factory. Je ne
pense pas qu'un compilateur est le droit de zapper l'appel à register.
Si j'ai bien compris, qu'importe. Ce n'est pas l'ObjectN::d qui nous
intéresse, mais les effets de borde de sont initialisation.
Dans la pratique, ceci n'est pas un problème, parce que toutes les
implémentations effectuent les initialisations dynamiques avant main, À
CONDITION que le fichier objet est linké statiquement. (Attention aux
DLL ou .so.)
En gros, si tu spécifies les fichiers objets explicitement, et que tu
linkes tout statiquement, la technique fonctionne. Sinon, il faut faire
attention.
Une technique qui m'a servie parfois dans la passée, c'est de rendre les
instances de fabrique publique, puis d'écrire une source C++ qui en
contient leurs adresses dans un tableau :
Pour ceux qui se plain que ça veut dire que je dois maintenir une liste
quelque part avec tous les types, tout ce que je peux dire, c'est que
cette liste, il faut que je le maintient d'une façon ou d'une autre.
Si j'ai bien compris, qu'importe. Ce n'est pas l'ObjectN::d qui nous
intéresse, mais les effets de borde de sont initialisation.
Dans la pratique, ceci n'est pas un problème, parce que toutes les
implémentations effectuent les initialisations dynamiques avant main, À
CONDITION que le fichier objet est linké statiquement. (Attention aux
DLL ou .so.)
En gros, si tu spécifies les fichiers objets explicitement, et que tu
linkes tout statiquement, la technique fonctionne. Sinon, il faut faire
attention.
Une technique qui m'a servie parfois dans la passée, c'est de rendre les
instances de fabrique publique, puis d'écrire une source C++ qui en
contient leurs adresses dans un tableau :
Pour ceux qui se plain que ça veut dire que je dois maintenir une liste
quelque part avec tous les types, tout ce que je peux dire, c'est que
cette liste, il faut que je le maintient d'une façon ou d'une autre.
Si j'ai bien compris, qu'importe. Ce n'est pas l'ObjectN::d qui nous
intéresse, mais les effets de borde de sont initialisation.
Dans la pratique, ceci n'est pas un problème, parce que toutes les
implémentations effectuent les initialisations dynamiques avant main, À
CONDITION que le fichier objet est linké statiquement. (Attention aux
DLL ou .so.)
En gros, si tu spécifies les fichiers objets explicitement, et que tu
linkes tout statiquement, la technique fonctionne. Sinon, il faut faire
attention.
Une technique qui m'a servie parfois dans la passée, c'est de rendre les
instances de fabrique publique, puis d'écrire une source C++ qui en
contient leurs adresses dans un tableau :
Pour ceux qui se plain que ça veut dire que je dois maintenir une liste
quelque part avec tous les types, tout ce que je peux dire, c'est que
cette liste, il faut que je le maintient d'une façon ou d'une autre.
[...]Dans la pratique, ceci n'est pas un problème, parce que toutes les
implémentations effectuent les initialisations dynamiques avant
main, À CONDITION que le fichier objet est linké statiquement.
(Attention aux DLL ou .so.)
[...]En gros, si tu spécifies les fichiers objets explicitement, et que
tu linkes tout statiquement, la technique fonctionne. Sinon, il faut
faire attention.
Voila le probleme, c'est que ma fabrique est justement dans une dll!
Donc le compilo ne sait pas encore comment vont s'utiliser les
fonctions que j'enregistre dans la map.
Une technique qui m'a servie parfois dans la passée, c'est de rendre
les instances de fabrique publique, puis d'écrire une source C++ qui
en contient leurs adresses dans un tableau :
[...]
C'est a peu de chose pres ce que je fais actuellement. Mais comme il
faut maintenir cette table, je ne trouvais pas ca "elegant".
Alors je me demandais s'il existait d'autres methodes pour enregistrer
automatiquement les objets sans devoir recourir a cet genre
d'"astuces" pour forcer le compilateur a evaluer le code
d'enregistrement.
[...]Pour ceux qui se plain que ça veut dire que je dois maintenir une
liste quelque part avec tous les types, tout ce que je peux dire,
c'est que cette liste, il faut que je le maintient d'une façon ou
d'une autre.
[...]
C'est exactement cette consequence qui me gene!
[...]
Dans la pratique, ceci n'est pas un problème, parce que toutes les
implémentations effectuent les initialisations dynamiques avant
main, À CONDITION que le fichier objet est linké statiquement.
(Attention aux DLL ou .so.)
[...]
En gros, si tu spécifies les fichiers objets explicitement, et que
tu linkes tout statiquement, la technique fonctionne. Sinon, il faut
faire attention.
Voila le probleme, c'est que ma fabrique est justement dans une dll!
Donc le compilo ne sait pas encore comment vont s'utiliser les
fonctions que j'enregistre dans la map.
Une technique qui m'a servie parfois dans la passée, c'est de rendre
les instances de fabrique publique, puis d'écrire une source C++ qui
en contient leurs adresses dans un tableau :
[...]
C'est a peu de chose pres ce que je fais actuellement. Mais comme il
faut maintenir cette table, je ne trouvais pas ca "elegant".
Alors je me demandais s'il existait d'autres methodes pour enregistrer
automatiquement les objets sans devoir recourir a cet genre
d'"astuces" pour forcer le compilateur a evaluer le code
d'enregistrement.
[...]
Pour ceux qui se plain que ça veut dire que je dois maintenir une
liste quelque part avec tous les types, tout ce que je peux dire,
c'est que cette liste, il faut que je le maintient d'une façon ou
d'une autre.
[...]
C'est exactement cette consequence qui me gene!
[...]Dans la pratique, ceci n'est pas un problème, parce que toutes les
implémentations effectuent les initialisations dynamiques avant
main, À CONDITION que le fichier objet est linké statiquement.
(Attention aux DLL ou .so.)
[...]En gros, si tu spécifies les fichiers objets explicitement, et que
tu linkes tout statiquement, la technique fonctionne. Sinon, il faut
faire attention.
Voila le probleme, c'est que ma fabrique est justement dans une dll!
Donc le compilo ne sait pas encore comment vont s'utiliser les
fonctions que j'enregistre dans la map.
Une technique qui m'a servie parfois dans la passée, c'est de rendre
les instances de fabrique publique, puis d'écrire une source C++ qui
en contient leurs adresses dans un tableau :
[...]
C'est a peu de chose pres ce que je fais actuellement. Mais comme il
faut maintenir cette table, je ne trouvais pas ca "elegant".
Alors je me demandais s'il existait d'autres methodes pour enregistrer
automatiquement les objets sans devoir recourir a cet genre
d'"astuces" pour forcer le compilateur a evaluer le code
d'enregistrement.
[...]Pour ceux qui se plain que ça veut dire que je dois maintenir une
liste quelque part avec tous les types, tout ce que je peux dire,
c'est que cette liste, il faut que je le maintient d'une façon ou
d'une autre.
[...]
C'est exactement cette consequence qui me gene!