我已经实现了这样的模板缓冲类:
template <class T, class Impl>
class base_hardware_buffer : Impl
{
public:
typedef const T& const_reference;
typedef T* pointer;
void push_back(reference r)
{
// Do some generic operation, call impl when needed
// ...
}
pointer map()
{
static_cast<Impl*> (this)->map();
}
// ... etc
};
然后我定义了两个实现,一个用于OpenGL,另一个用于DirectX,每个实例都在自己的动态库中实例化。 对于OpenGL:
template <class T>
class glBuffer : base_hardware_buffer<T, glBuffer<T> >
{
public:
typedef T* pointer;
pointer map()
{
// Actual implementation of map
}
// Other implementation specific operation and members go here
};
这一切都很好,效果很好。 现在我的问题是我的队友在我的子系统上面的层上工作想要实现一个需要访问缓冲区的算法。
如何在不将特定实现暴露/硬编码到代码中的情况下给他统一访问缓冲区,也不会影响类型安全性?
答案 0 :(得分:0)
我可以解释一下我是如何实现类似问题的解决方案的。
基本上我有一个“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,则在创建GL2Handler时使用D3D9实现,它使用GL2实现等。
编辑:在回答您的评论时,您无法执行以下操作:
template< typename Type > bool LockBuffer( unsigned int flags, Type** pData );
或者您是否要专门创建一个类,其中唯一可返回类型是使用它创建的类型?这会有点复杂,因为你突然有大量的不同类型需要分配给各种函数指针,因为传递给模板的2个单独类型会创建2个不同的函数。