Я могу объяснить, как я реализовал решение аналогичной проблемы.
В основном у меня есть функция "CreateBuffer", которая возвращает указатель на "базовый" буфер. Затем, когда я вызываю функции из этого базового буфера, они переходят к соответствующей функции.
class BaseBuffer
{
public:
BaseBuffer(void);
virtual ~BaseBuffer(void);
virtual bool Init( GFXHandler* pHandler, unsigned int usage, unsigned int sizeofData ) { return false; }
virtual bool Shutdown() = 0;
virtual bool LockBuffer( unsigned int flags, void** ppData ) = 0;
virtual bool UnlockBuffer() = 0;
};
Теперь уловка, которую я использовал, чтобы убедиться, что конечному пользователю все равно, как реализована внутренняя реализация буфера, заключалась в том, чтобы сделать CreateBuffer указателем на функцию. Затем, когда я устанавливаю графический обработчик (например, GL2Handler), я назначаю функцию «GL2CreateBuffer» указателю функции «CreateBuffer».
Таким образом, конечный пользователь может просто сделать следующее:
BaseBuffer* pBuffer = CreateBuffer();
pBuffer->Init( /*init params*/ );
void* pData = NULL;
pBuffer->LockBuffer( /*lock flags*/, &pData );
memcpy( pData, pOriginalData, sizeOfOriginalData );
pBuffer->UnlockBuffer();
Работа выполнена. Если был создан D3D9Handler, он использовал реализацию D3D9, если был создан GL2Handler, он использовал реализацию GL2 и т. Д.
Редактировать: В ответ на ваш комментарий вы не сможете сделать следующее:
template< typename Type > bool LockBuffer( unsigned int flags, Type** pData );
Или вы хотите специально создать класс, в котором единственным возвращаемым типом является тип, с которым он был создан? Это было бы немного сложнее, поскольку у вас внезапно появилось множество различных типов, которые потребовали бы назначения различным указателям на функции, поскольку два отдельных типа, передаваемых в шаблон, создают две разные функции.