void* как неизвестный тип переменной
Вопрос
В настоящее время я работаю над движком спрайтов на C++.У меня есть абстрактный класс IEngine с виртуальной функцией init_api.Это занимает пустоту*.
// Initialise the engines' API
// api_params - void* to api parameters for initalisation
// hWnd - window handle
virtual bool init_api( void* api_params, HWND hWnd ) = 0;
Затем у меня есть класс CEngineDX, реализованный в DirectX.Затем api_params преобразуется в D3DPRESENT_PARAMETERS*, чтобы его можно было использовать для инициализации DirectX.
// Cast api_params to a D3DPRESENT_PARAMETERS
D3DPRESENT_PARAMETERS* presentParams = NULL;
presentParams = reinterpret_cast< D3DPRESENT_PARAMETERS* >( api_params );
Я вполне доволен этой настройкой, но хотел бы, если хотите, узнать мнение других программистов об этом «решении».
Спасибо за ответы!
Карл
Решение
Другой способ сделать это — просто иметь общий заголовок и разные файлы *.cpp для каждой реализации.Таким образом, вы можете включить в свой проект только файлы D3D или только файлы OGL.ИМО, лучше выбирать API во время компиляции, чтобы не связываться с обеими библиотеками.
Что касается пустоты*, то она мне не очень нравится.Я думаю, вам лучше определить свои собственные типы, а затем сопоставить их с типами API с помощью структур/классов-оболочек и определений типов.Вы можете объявить их и поместить фактическую реализацию в свои файлы *.cpp.
Еще одним преимуществом этого метода является то, что вы не платите за ненужные виртуальные функции, хотя я понимаю, что стоимость виртуального вызова довольно мала.
Другие советы
Это относительно распространенная проблема, связанная с изменением типов аргументов в иерархиях наследования;ваш подкласс хочет специализировать тип «api_params» из родительского класса.
Я думаю, что это нормально, но это C-подобно.Я думаю, что лучшим решением было бы сделать init_api
невиртуальный и реализовать его с правильным типом в подклассе.Во всяком случае, скорее всего, D3DPRESENT_PARAMETERS
Структура имеет смысл только с движком DirectX, так почему бы не разместить ее в подклассе, которому она логически принадлежит?
Ну, вы можете использовать шаблоны (если вам не нравится приведение типов), но в этом случае вам придется отказаться от вашей иерархии.
template<class T>
struct Engine {
bool init_api(const T& params, HWND hWnd);
};
//specialize for DirectX
template<>
struct Engine <D3DPRESENT_PARAMETERS> {
bool init_api(const D3DPRESENT_PARAMETERS& params, HWND hWnd) {
return true;
}
};
Но используйте что-то, что вписывается в общую схему вещей.
Мне не очень нравится этот API.Зачем использовать указатель void?Почему бы не сделать первый параметр указателем или ссылкой на D3DPRESENT_PARAMETERS
?Вы знаете, что так и должно быть, верно?Это более безопасно с точки зрения типов.