OVH Cloud OVH Cloud

Héritage ou dll ?

24 réponses
Avatar
Spoofix
Bonjour,

Je voudrais commencer à écrire un moteur 3D, mais pour lequel ou pourrait
choisir entre OpenGL et DirectX. En fait, mon probleme C++ est le suivant :
certaines fonctions seront écrites 2x : une fois pour OpenGL et une fois
pour DirectX. Je voudrais avoir qu'un seul nom de fonction pour ces 2
fonctions.
J'ai pensé à 2 solutions :

1. Avoir 2 dll séparées, contenant les fonctions concernées, et charger
dynamiquement la bonne au démarrage. Est-ce possible (je n'ai encore jamais
programmé de dll) ?

2. Avoir une classe mère CMaClasse avec des fonctions membres virtuelles (ex
: virtual MaFonction()=0 ). Puis créer 2 classe filles : CMaClasse_gl et
CMaClasse_dx. Et faire :

CMaClasse *Objet;
if (OpenGL)
Objet = new CMaClass_gl;
else
Objet = new CMaClass_dx;

Qu'en pensez vous ? Avez d'autres solutions ? Sachant que je recherche la
méthode la plus rapide...

Merci d'avance.
Clément.

10 réponses

1 2 3
Avatar
Vincent Richard

Je voudrais commencer à écrire un moteur 3D, mais pour lequel ou pourrait
choisir entre OpenGL et DirectX. En fait, mon probleme C++ est le suivant
: certaines fonctions seront écrites 2x : une fois pour OpenGL et une fois
pour DirectX. Je voudrais avoir qu'un seul nom de fonction pour ces 2
fonctions.
J'ai pensé à 2 solutions :
1. Avoir 2 dll séparées,


Les DLL c'est HS ici.
Je vais donc te donner une "solution C++".

2. Avoir une classe mère CMaClasse avec des fonctions membres virtuelles
CMaClasse *Objet;
if (OpenGL)
Objet = new CMaClass_gl;
else
Objet = new CMaClass_dx;

Qu'en pensez vous ? Avez d'autres solutions ? Sachant que je recherche la
méthode la plus rapide...


Au passage, tester à chaque création d'objet si on est en mode DX ou OpenGL
n'est pas très performant (ni très lisible, d'ailleurs).

Je te propose de faire une hiérarchie de classes abstraites :

Moteur <-- contiennent des fonctions virtuelles pures _uniquement_
Objet
Scene
...

et de classes concrètes :

MoteurDX et MoteurOGL <-- contiennent l'implémentation
ObjetDX et ObjetOGL
SceneDX et SceneOGL
...

et de créer des fabriques abstraites et concrètes :

FabriqueMoteur (abstraite) et FabriqueMoteurDX, FabriqueMoteurOGL
FabriqueObjet et FabriqueObjetDX, FabriqueObjetOGL

Ensuite, au niveau de l'utilisation :

// Instanciation d'un moteur
Moteur* m = FabriqueMoteur::instance().create("OpenGL");

// Instanciation d'une scène
Scene* s = m->fabriqueScene().create();

// Instanciation d'objets
Objet* o1 = s->fabriqueObjet().create();
Objet* o2 = s->fabriqueObjet().create();

ce qui fait qu'on ne travaille qu'avec des objets "abstraits".

Vincent

--
vmime, une bibliothèque C++ sous licence GPL pour parser et générer
des messages au format MIME : http://www.sourceforge.net/projects/vmime/

Avatar
Spoofix
Bonjour,

Les DLL c'est HS ici.


Désolé...

Je vais donc te donner une "solution C++".


Merci beaucoup pour ta proposition, mais j'aurais quelques questions a te
poser....


et de créer des fabriques abstraites et concrètes :

FabriqueMoteur (abstraite) et FabriqueMoteurDX, FabriqueMoteurOGL
FabriqueObjet et FabriqueObjetDX, FabriqueObjetOGL


Qu'appelles tu des "fabriques" ? Ce sont des classes ou des fonctions
membres ? Pourrais tu me donner un exemple de comment déclarer toutes les
classes que tu m'indiques ?

Ensuite, au niveau de l'utilisation :

// Instanciation d'un moteur
Moteur* m = FabriqueMoteur::instance().create("OpenGL");


Je ne comprend pas bien cette ligne.... que renvoie instance() ?

// Instanciation d'une scène
Scene* s = m->fabriqueScene().create();

// Instanciation d'objets
Objet* o1 = s->fabriqueObjet().create();
Objet* o2 = s->fabriqueObjet().create();


La fonction est-elle une sorte de constructeur, mais appelée juste apres le
veritable constructeur....

Désolé si je semble un peu perdu, mais je viens d'apprendre les notions
d'heritages (je viens du C, et j'apprend le C++ que depuis quelques
mois....)

Merci encore.
Clément.

Avatar
Christophe Lephay
Spoofix wrote:
Qu'appelles tu des "fabriques" ? Ce sont des classes ou des fonctions
membres ? Pourrais tu me donner un exemple de comment déclarer toutes
les classes que tu m'indiques ?


Une fabrique est une classe responsable de la création d'objets d'une ou
(plus généralement) plusieurs classes. En général, une fabrique crée un
objet dont le type (ou la classe) dépend d'un paramètre transmis.

Ensuite, au niveau de l'utilisation :

// Instanciation d'un moteur
Moteur* m = FabriqueMoteur::instance().create("OpenGL");


Je ne comprend pas bien cette ligne.... que renvoie instance() ?


C'est un autre modèle classique de conception ("Design Pattern"), appelé
singleton, qui garantit qu'une seule instance d'une classe donnée peut être
créé. Le fait de passer par la création d'un objet unique, plutôt que
d'utiliser des fonctions libres ou des membres statiques, garantit, via la
création de cet objet unique, que le système sera correctement initialisé
avant le premier appel de fonction (via son constructeur).

// Instanciation d'une scène
Scene* s = m->fabriqueScene().create();

// Instanciation d'objets
Objet* o1 = s->fabriqueObjet().create();
Objet* o2 = s->fabriqueObjet().create();


La fonction est-elle une sorte de constructeur, mais appelée juste
apres le veritable constructeur....


La différence, c'est que la création d'objet est déléguée. Notemment, il
suffit de remplacer

Moteur* m = FabriqueMoteur::instance().create("OpenGL");

par


Moteur* m = FabriqueMoteur::instance().create("DirectX");

pour que les objets créés soient complètement différent, ce qui permet de
pouvoir adapter l'application facilement, en changeant juste une ligne, ce
qui n'est pas le cas si on avait directement :

Objet* o1 = new DOpenGLObject;

(dans ce cas, il faut parcourir et modifier tout le code pour passer
d'OpenGL à DirectX).

Désolé si je semble un peu perdu, mais je viens d'apprendre les
notions d'heritages (je viens du C, et j'apprend le C++ que depuis
quelques mois....)


Celà risque de faire pas mal de choses nouvelles pour toi :)

Dès que tu commences à te sentir un peu à l'aise avec le langage(*),
procures toi au plus vite "Design Pattern" [Gamma, Helm, Johnson,
Vlissides]...

(*) bien que tu puisses étudier les deux en parallèle, les DPs étant
relativement indépendant du langage

Chris


Avatar
Spoofix
Merci pour ces éclaircissements.
Je me suis donc renseigné sur ces fameux singletons et fabriques, et il y a
quelques trucs que je ne comprend pas dans le code d'initialisation que
Vincent m'a donné.

Le code :
Moteur* m = FabriqueMoteur::instance().create("OpenGL");
Ma question :
Ici, FabriqueMoteur est un singleton, et FabriqueMoteur::instance()
retourne l'instance unique de la classe FabriqueMoteur, c'est ca ? Et create
est une fonction membre de FabriqueMoteur, qui fait par ex. "return new
MoteurDX();" ? Dites moi si je me trompe....

Le code :
// Instanciation d'une scène
Scene* s = m->fabriqueScene().create();
Ma question :
Comment est définie fabriqueScene ? Est-ce une fonction membre de
Moteur, ou est-ce une classe encapsulée dans Moteur (mais je ne pense pas
qu'on l'utiliserait comme ca....) ? Ou est-ce toute autre chose ?

Voila, merci encore pour vos réponses.
Clément.
Avatar
Vincent Richard

Le code :
// Instanciation d'une scène
Scene* s = m->fabriqueScene().create();
Ma question :
Comment est définie fabriqueScene ? Est-ce une fonction membre de
Moteur, ou est-ce une classe encapsulée dans Moteur (mais je ne pense pas
qu'on l'utiliserait comme ca....) ? Ou est-ce toute autre chose ?


fabriqueScene() est une fonction qui renvoie une instance de fabrique
pour des objets "Scene" :

// Fabrique scène abstraite
class FabriqueScene
{
public:

virtual Objet* create(...) = 0;
};

// Fabriques scène concrètes
class FabriqueSceneDX : public FabriqueScene
{
Objet* create(...) { return new ObjetDX(...); }
};

class FabriqueSceneOGL : public FabriqueScene
{
Objet* create(...) { return new ObjetOGL(...); }
};


// Fabrique moteur abstraite
class FabriqueMoteur
{
public:

virtual FabriqueScene& fabriqueScene() = 0;
};

// Fabriques moteur concrètes
class FabriqueMoteurDX : public FabriqueMoteur
{
public:

FabriqueScene& fabriqueScene()
{
static FabriqueSceneDX fab;
return fab;
}
};

class FabriqueMoteurOGL : public FabriqueMoteur
{
public:

FabriqueScene& fabriqueScene()
{
static FabriqueSceneOGL fab;
return fab;
}
};


Vincent

--
vmime, une bibliothèque C++ sous licence GPL pour parser et générer
des messages au format MIME : http://www.sourceforge.net/projects/vmime/

Avatar
Bruno
Je peux te conseiller de lire la série d'articles suivantes :

http://www.gamedev.net/reference/programming/features/rendererdll1/
http://www.gamedev.net/reference/programming/features/rendererdll2/
http://www.gamedev.net/reference/programming/features/rendererdll3/

C'est exactement ce que tu veux faire, je n'approuve pas à 100% ses idées
(de l'auteur), mais ya des trucs sympa que tu pourras apprendre je pense...

--

"Spoofix" <spoofix[ENLEVEZ_CA]@free.fr> a écrit dans le message de
news:3fa14547$0$258$
Bonjour,

Je voudrais commencer à écrire un moteur 3D, mais pour lequel ou pourrait
choisir entre OpenGL et DirectX. En fait, mon probleme C++ est le suivant
:

certaines fonctions seront écrites 2x : une fois pour OpenGL et une fois
pour DirectX. Je voudrais avoir qu'un seul nom de fonction pour ces 2
fonctions.
J'ai pensé à 2 solutions :

1. Avoir 2 dll séparées, contenant les fonctions concernées, et charger
dynamiquement la bonne au démarrage. Est-ce possible (je n'ai encore
jamais

programmé de dll) ?

2. Avoir une classe mère CMaClasse avec des fonctions membres virtuelles
(ex

: virtual MaFonction()=0 ). Puis créer 2 classe filles : CMaClasse_gl et
CMaClasse_dx. Et faire :

CMaClasse *Objet;
if (OpenGL)
Objet = new CMaClass_gl;
else
Objet = new CMaClass_dx;

Qu'en pensez vous ? Avez d'autres solutions ? Sachant que je recherche la
méthode la plus rapide...

Merci d'avance.
Clément.




Avatar
Spoofix
"Bruno" a écrit dans le message de
news:3fa54dfe$0$13273$
Je peux te conseiller de lire la série d'articles suivantes :

http://www.gamedev.net/reference/programming/features/rendererdll1/
http://www.gamedev.net/reference/programming/features/rendererdll2/
http://www.gamedev.net/reference/programming/features/rendererdll3/



Merci beaucoup pour les liens, je vais aller voir ca.....

Avatar
Spoofix
fabriqueScene() est une fonction qui renvoie une instance de fabrique
pour des objets "Scene" :


Quel est l'avantage de cela, pourquoi ne pas renvoyer directement une
instance de CScene ?
Clément.

Avatar
Christophe Lephay
Spoofix wrote:
fabriqueScene() est une fonction qui renvoie une instance de fabrique
pour des objets "Scene" :


Quel est l'avantage de cela, pourquoi ne pas renvoyer directement une
instance de CScene ?


Parce qu'une scène fonctionnant avec DirectX n'est pas nécessairement de la
même classe qu'une autre pour OpenGL...

Chris


Avatar
Spoofix
Quel est l'avantage de cela, pourquoi ne pas renvoyer directement une
instance de CScene ?


Parce qu'une scène fonctionnant avec DirectX n'est pas nécessairement de
la

même classe qu'une autre pour OpenGL...


Je crois que je me suis mal exprimé : je voulais dire : pourquoi ne
renvoie-t-on pas directement une instance de SceneDX ou de SceneOGL, sans
passer par une fabrique ? Ce serait un peu comme une fabrique intégrée dans
Moteur....

Clément.


1 2 3