2013-08-04 27 views
2

我编码一个游戏引擎类,我一直建议增加此#定义处理多个API以这种方式:在运行时或编译时更改API?

#ifdef OGL 
    typedef COpenGl CBaseApi; 
#elif defined(OGLES) 
    typedef COpenGlEs CBaseApi; 
#elif defined(DX9) 
    typedef CDirectX9 CBaseApi; 
#elif defined(DX10) 
    typedef CDirectX10 CBaseApi; 
#elif defined(DX11) 
    typedef CDirectX11 CBaseApi; 
#endif 

而且我有两个问题:我怎样才能获得以上工作?

我想:

class CBaseAPI 
{ 
    //abstract class, virtual functions 
} 
class COpenGL : public CBaseAPI 
{ 
    //implementations 
} 

但正如我预料它没有工作。

第二个问题是,这种#define方法比使用某种工厂更好吗?我最初是这样做的:

//inside the Main program 
myGameEngine.Initialize(GraphicAPI::DirectX11); 

//inside the Initialize function 
void GameEngine::Initialize(GraphicAPI graphicAPI) 
{ 
    switch(graphicAPI) 
    { 
     case GraphicAPI::DirectX11: 
     { 
      //Defined as private members:     
      //BaseAPI graphicAPI; 

      //class CDirectX11 : public BaseAPI 

      graphicAPI = new CDirectX11(); 
     } 
     //other cases here 
    } 
} 

这些方法有什么优点和缺点,什么是首选吗?

回答

-1

第二个是可怕的。两阶段初始化非常容易出错,在一般情况下,游戏完全不需要在运行时更改渲染API。使用接口和继承完全浪费时间和性能,更不用说失去了很好的强类型。

对于#define,没有必要通过继承链接这些类。你可能会更好地使用模板,但条件编译是预处理器的功能。简单的使用场景:

class OGL { 
public: 
    void dostuff(); 
}; 
class DX { 
public: 
    void dostuff(); 
}; 
class GameEngine { 
#ifdef USE_OPENGL 
    OGL BaseAPI; 
#else 
    DX BaseAPI; 
#endif 
public: 
    void dostuff() { BaseAPI.dostuff(); } 
}; 

此外,CClass? Owch。你需要找到新的学习材料,好友。

+0

所以你将不得不重新编译来改变渲染API? – Hna

+0

@Hna能够在运行时更改渲染API不值得额外的性能成本。 – Borgleader

+0

@Borgleader不要在运行时改变它。更像是读取命令行参数或用户设置文件,然后选择渲染API。你不能用预处理器指令来做到这一点。 – Hna

0

您似乎有一个与基类(CBaseApi)具有相同名称的typedef。这不会很好。

您是不是要找这样的:

class CBaseAPI 
{ 
    //abstract class, virtual functions 
}; 
class COpenGlEs : public CBaseAPI 
{ 
    // implementations 
}; 

#ifdef OGL 
    typedef COpenGl BaseApiImpl; 
#elif defined(OGLES) 
    typedef COpenGlEs BaseApiImpl; 
#elif defined(DX9) 
    typedef CDirectX9 BaseApiImpl; 
#elif defined(DX10) 
    typedef CDirectX10 BaseApiImpl; 
#elif defined(DX11) 
    typedef CDirectX11 BaseApiImpl; 
#endif