Шаблон, к которому вы идете, может быть готов, но вы можете пожалеть об этом позже. Из вашей настройки я бы сделал вывод, что у вас есть две перегрузки WindowClosed()
- одна с параметром GLFWwindow
, а другая с параметром типа WinAPI. Первый будет использовать методы GLFW, чтобы определить, закрыто ли окно, а второй будет использовать Windows API. Одной из проблем является организация: сколько файлов содержат специфичные для GLFW методы? Может быть, у вас есть файл как с методами GLFW, так и с методами Win API? Это не обязательно неправильно, но это может быть боль в долгосрочной перспективе. Другая проблема состоит в том, что этот подход отличается от традиционного объектно-ориентированного подхода.
Тем не менее, давайте не будем заставлять вас идти одним путем из-за недостатка знаний. Чтобы этот подход работал, вы можете использовать препроцессор и typedef
. При компиляции для Mac вы должны использовать строку типа typedef PatternGLFW3_VULKAN WindowType;
. При компиляции для Windows вы должны использовать строку, определяющую WindowType
как соответствующий тип Windows. Выбор между этими строками будет выполнен с помощью #ifdef WINDOWS
(или любого другого условия, наиболее подходящего). Тогда можно объявить, что getWindow()
возвращает WindowType
.
Лучший подход (который вы реализовали в комментариях) - это перенести функциональность на объекты окна. Вместо function(object)
используйте object.function()
. Это требует больше виртуальных функций в вашем классе интерфейса, но есть преимущество в том, что у вас меньше файлов, которые зависят от ОС.
class PatternWindow
{
public:
PatternWindow();
virtual ~PatternWindow();
virtual void initialize() = 0;
virtual void destroy () = 0;
virtual bool closed () = 0; // <-- New pure virtual function
};
class PatternGLFW3_VULKAN : public PatternWindow
{
public:
PatternGLFW3_VULKAN ();
~PatternGLFW3_VULKAN();
virtual void initialize();
virtual void destroy();
virtual bool closed(); // <-- OS-specific code is no longer in an extra file
private:
GLFWwindow * _window;
};
Тогда в вашей основной функции вызов будет:
while(!Window::getPatternWindow()->closed())
Есть еще один шаг, который вы могли бы рассмотреть. (Соответственно, в вопросе недостаточно подробностей, чтобы определить, является ли этот вариант приемлемым.) Вам может не понадобиться полиморфизм для того, что вы пытаетесь сделать. Предположим, вы использовали следующее объявление:
class PatternWindow
{
#ifdef WINDOWS // Or whatever test is appropriate
typedef PatternGLFW3_VULKAN * WindowType;
#else
typedef /* Windows API type */ WindowType;
#endif
public:
PatternWindow();
~PatternWindow();
void initialize();
void destroy ();
bool closed ();
private:
WindowType _window;
};
Этот интерфейс больше не поддерживает полиморфизм. Это плохо? Вам нужно несколько классов, производных от PatternWindow
в одной операционной системе ? Возможно нет. Вот потенциальный файл реализации для этого класса.
#include "PatternWindow.h"
#ifdef WINDOWS // Or whatever test is appropriate
#include "PatternWinAPI.src" // <-- File with an implementation based on Win API
#else
#include "PatternGLFW.src" // <-- File with an implementation based on GLFW
#endif
Если вам не нравится расширение .src
, используйте что-то еще. Только не делайте эти файлы похожими на что-то для самостоятельной компиляции. Каждый файл будет иметь реализацию, соответствующую используемому им API. Например, PatternGLFW.src
может содержать определение функции, подобное следующему:
void PatternWindow::initialize()
{
_window = glfwCreateWindow(...);
// Etc.
}
Это устраняет издержки полиморфизма и, по-видимому, не создает бремени кодирования. Кроме того, вам не нужно отслеживать, какие файлы нужны для каких операционных систем (более простая настройка сборки). Однако организация PatternWindow.cpp
встречается редко.