Writing a program framework. Classes and stuff.
- AndrewAPrice
- Member
- Posts: 2299
- Joined: Mon Jun 05, 2006 11:00 pm
- Location: USA (and Australia)
Writing a program framework. Classes and stuff.
I'm writing a game framework. I am using my own classes as wrappers around DirectX (and at a later point, OpenGL) classes.
Anyway, say my texture class contains the private member "IDirect3DTexture9 *m_d3dTexture;" (a Direct3D texture). This is defined in my header file which is included in the framework project and also end projects wishing to access my texture class.
But, the problem lies within abstracting my framework away from Direct3D. For an end program to include my texture.h they must have d3d9.h and d3dx9.h on their system (for IDirect3DTexture9) which means they must have the DirectX SDK installed on their system. I want to avoid this. I have virtually every game framework/engine do this (you don't need any DX or OpenGL SDK installed, just the link with the engine's dynamic library).
I do not want to have to convert every DirectX specific member to void * and then refer to them as ((IDirect3DSomeClass)myMember) everywhere in my code.
Anyway, say my texture class contains the private member "IDirect3DTexture9 *m_d3dTexture;" (a Direct3D texture). This is defined in my header file which is included in the framework project and also end projects wishing to access my texture class.
But, the problem lies within abstracting my framework away from Direct3D. For an end program to include my texture.h they must have d3d9.h and d3dx9.h on their system (for IDirect3DTexture9) which means they must have the DirectX SDK installed on their system. I want to avoid this. I have virtually every game framework/engine do this (you don't need any DX or OpenGL SDK installed, just the link with the engine's dynamic library).
I do not want to have to convert every DirectX specific member to void * and then refer to them as ((IDirect3DSomeClass)myMember) everywhere in my code.
My OS is Perception.
Re: Writing a program framework. Classes and stuff.
class XYZ;MessiahAndrw wrote:I do not want to have to convert every DirectX specific member to void * and then refer to them as ((IDirect3DSomeClass)myMember) everywhere in my code.
class A {
XYZ *something;
XYZ &func(XYZ &something);
};
You don't need the declaration for XYZ to get this to work. Just forward declare it.
- AndrewAPrice
- Member
- Posts: 2299
- Joined: Mon Jun 05, 2006 11:00 pm
- Location: USA (and Australia)
Re: Writing a program framework. Classes and stuff.
How about for structures?Candy wrote:class XYZ;MessiahAndrw wrote:I do not want to have to convert every DirectX specific member to void * and then refer to them as ((IDirect3DSomeClass)myMember) everywhere in my code.
class A {
XYZ *something;
XYZ &func(XYZ &something);
};
You don't need the declaration for XYZ to get this to work. Just forward declare it.
My OS is Perception.
Re: Writing a program framework. Classes and stuff.
struct XYZ;MessiahAndrw wrote:How about for structures?Candy wrote:class XYZ;MessiahAndrw wrote:I do not want to have to convert every DirectX specific member to void * and then refer to them as ((IDirect3DSomeClass)myMember) everywhere in my code.
class A {
XYZ *something;
XYZ &func(XYZ &something);
};
You don't need the declaration for XYZ to get this to work. Just forward declare it.
Did you at least try that?
- Kevin McGuire
- Member
- Posts: 843
- Joined: Tue Nov 09, 2004 12:00 am
- Location: United States
- Contact:
Thats about the reason why I generally tend to not ask questions unless the question is about something that is:
- Above my ability to mentally manipulate/conceptualize/understand.
- Lacks any method to determine such as:
- Pseudo/Partial Random Experimentation; changing inputs to determine effect on outputs.
- Researching for existing solutions.
- Isolation of a problem from the solution by removing/verifying surrounding parts.
- AndrewAPrice
- Member
- Posts: 2299
- Joined: Mon Jun 05, 2006 11:00 pm
- Location: USA (and Australia)
Are classes are just really structures except with methods?
Could I have:
private-header.h:
and in:
public-header.h:
So I don't need to define IDirect3DDevice9. Do I even need to include the private methods in my public header at all?
Could I have:
private-header.h:
Code: Select all
class MyClass
{
public:
// constructor and methods here
private:
int someMember;
IDirect3DDevice9 *superHiddenMember;
int someOtherMember
};
public-header.h:
Code: Select all
class MyClass
{
public:
// constructor and methods here
private:
int someMember;
int someOtherMember
};
My OS is Perception.
You should problably look into the abstract factory pattern. consider the following code fragment. It defines an abstract class line and a pure virtual method to draw itself.
Next it define 3 line classes for Vesa, DrawDib and OpenGL with draw the line using the methods available for each interface.
then you have three factories GUIVesaFactory, GUIDrawDibFactory and GUIOpenGLFactory which allow us to create the Line object(and other objects ofcourse) for the above mentioned classes.
then finally there is the abstract factory GuiFactory which gets the appropriate factory via a name.
as you can see in the main function you don't see any reference to what rendering platform you use. There are only the primitive you need.
perfect encapsulation...
hope this helps
Next it define 3 line classes for Vesa, DrawDib and OpenGL with draw the line using the methods available for each interface.
then you have three factories GUIVesaFactory, GUIDrawDibFactory and GUIOpenGLFactory which allow us to create the Line object(and other objects ofcourse) for the above mentioned classes.
then finally there is the abstract factory GuiFactory which gets the appropriate factory via a name.
Code: Select all
#include <stdio.h>
#include <string.h>
typedef class Line {
protected: int _x1, _y1, _x2, _y2;
public: Line(int x1, int y1, int x2, int y2) : _x1(x1), _y1(y1), _x2(x2), _y2(y2) {}
public: virtual void draw(void) = 0;
} Line;
typedef class DrawDibLine : public Line {
public: DrawDibLine(int x1, int y1, int x2, int y2) : Line(x1, y1, x2, y2) {}
public: virtual void draw(void) {
printf("DrawDib::Line(%d, %d)-(%d, %d)\n", _x1, _y1, _x2, _y2);
}
} DrawDibLine;
typedef class OpenGLLine : public Line {
public: OpenGLLine(int x1, int y1, int x2, int y2) : Line(x1, y1, x2, y2) {}
public: virtual void draw(void) {
printf("OpenGL::Line(%d, %d)-(%d, %d)\n", _x1, _y1, _x2, _y2);
}
} OpenGLLine;
typedef class VesaLine : public Line {
public: VesaLine(int x1, int y1, int x2, int y2) : Line(x1, y1, x2, y2) {}
public: virtual void draw(void) {
printf("Vesa::Line(%d, %d)-(%d, %d)\n", _x1, _y1, _x2, _y2);
}
} VesaLine;
typedef class GUIFactory {
public: static GUIFactory * GetInstance(char *);
public: virtual Line * CreateLine(int x1, int y1, int x2, int y2) = 0;
} GUIFactory;
typedef class GUIDrawDibFactory : public GUIFactory {
public: virtual Line * CreateLine(int x1, int y1, int x2, int y2) {
return(new DrawDibLine(x1, y1, x2, y2));
}
} GUIDrawDibFactory;
typedef class GUIOpenGLFactory : public GUIFactory {
public: virtual Line * CreateLine(int x1, int y1, int x2, int y2) {
return(new OpenGLLine(x1, y1, x2, y2));
}
} GUIOpenGLFactory;
typedef class GUIVesaFactory : public GUIFactory {
public: virtual Line * CreateLine(int x1, int y1, int x2, int y2) {
return(new VesaLine(x1, y1, x2, y2));
}
} GUIVesaFactory;
GUIFactory * GUIFactory::GetInstance(char * type) {
if(type != 0) {
if(strcmp(type, "DrawDib") == 0) {
return(new GUIDrawDibFactory);
}
else
if(strcmp(type, "OpenGL") == 0) {
return(new GUIOpenGLFactory);
}
else
if(strcmp(type, "Vesa") == 0) {
return(new GUIVesaFactory);
}
}
return(new GUIDrawDibFactory);
}
int main(int argc, char * argv[]) {
GUIFactory * guiFactory = GUIFactory::GetInstance(argv[1]);
/* actual gui calls for instance, button, window, etc.
Line * line = guiFactory->CreateLine(10, 10, 246, 246);
line->draw();
return(0);
}
perfect encapsulation...
hope this helps
Author of COBOS
You can add methods to a struct too. A class is a struct. The only difference is that a struct by default has public members (methods and variables) and a class by default has private members.MessiahAndrw wrote:Are classes are just really structures except with methods?
If your private methods are a part of the class interface, then yes, you do. There is a common method for hiding such implementation details, called the pImpl idiom, as well as the more generic interface definition, which requires you to define the interface and then implement it.Could I have:
private-header.h:and in:Code: Select all
class MyClass { public: // constructor and methods here private: int someMember; IDirect3DDevice9 *superHiddenMember; int someOtherMember };
public-header.h:So I don't need to define IDirect3DDevice9. Do I even need to include the private methods in my public header at all?Code: Select all
class MyClass { public: // constructor and methods here private: int someMember; int someOtherMember };
- AndrewAPrice
- Member
- Posts: 2299
- Joined: Mon Jun 05, 2006 11:00 pm
- Location: USA (and Australia)
I have an idea:
This is the public header:
And here's the private header:
Is this what you mean about pImpl?
Edit: I found this: http://en.wikipedia.org/wiki/Opaque_pointer#C.2B.2B
This is the public header:
Code: Select all
class IMyClass
{
public:
MyClass();
virtual void MyFunction();
};
Code: Select all
class MyClass_DX9 : public IMyClass
{
private:
int someMember;
IDirect3DDevice9 *superHiddenMember;
int someOtherMember;
};
Edit: I found this: http://en.wikipedia.org/wiki/Opaque_pointer#C.2B.2B
My OS is Perception.
Code: Select all
class Concrete : public Abstract {
class Impl;
Impl *pImpl;
public:
// Abstract functions that only forward
};
Code: Select all
#include <AwkwardImplementationHeader.h>
class Concrete::Impl {
// the actual local functions, local storage, etc
};
Concrete::func() { return pImpl->func(); }
- AndrewAPrice
- Member
- Posts: 2299
- Joined: Mon Jun 05, 2006 11:00 pm
- Location: USA (and Australia)
Here's an example of what I've decided to work with:
This is from texture.h
All .cpp inside files of my framework start with #define MGF_LIB to indicate it is a library source. That way, an end-program does not need to know how MGF::Texture works and can easily pass it around in its program and does not need the DirectX SDK installed. Library source files can still access the underlying IDirect3DTexture9* for rendering by using Texture.GetInternal()->m_texture.
This is from texture.h
Code: Select all
#ifndef _MGF_TEXTURE_H
#define _MGF_TEXTURE_H
#ifdef MGF_LIB
#include <d3d9.h>
#include <d3dx9.h>
#endif
namespace MGF
{
struct TextureInternal;
class Texture
{
public:
Texture(const char *name, IDirect3DDevice9 *device);
~Texture();
void SetNext(Texture *next);
Texture *GetNext();
const char *GetName();
TextureInternal *GetInternal();
private:
TextureInternal *m_internal;
};
#ifdef MGF_LIB
struct TextureInternal
{
Texture *m_next;
char *m_name;
IDirect3DTexture9 *m_texture;
};
#endif
}
#endif
My OS is Perception.