2013-08-04 3 views
2

я кодирование класса игрового движка, и я предложил, чтобы добавить #define, чтобы иметь дело с несколькими 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

У вас, похоже, есть typedef с тем же именем, что и базовый класс (CBaseApi). Это не будет хорошо.

вы имели в виду что-то вроде:

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 
Смежные вопросы