演员的DirectX接口的IUnknown指针
有相当多的接口在我的代码,我想封装在另一种方法,而不是在宏重复Release
代码,因为这是C++,我讨厌使用宏。我的最初尝试是写的方法如演员的DirectX接口的IUnknown指针
void SafeRelease(IUnknown **ppInterface) {
if(*ppInterface) {
(*ppInterface)->Release();
(*ppInterface) = nullptr;
}
}
但是将这种方法应用于一个IDirect3DSurface9 *
例如如SafeRelease(&mySurface)
产生错误IDirect3DSurface9 **
与IUnknown **
不兼容。
- 我在做什么在这里错了吗?
- 有没有更好的方法(希望不使用宏)来实现这样的功能?
这里是我的方法:
template <typename T> void SafeRelease(T*& ptr)
{
if(ptr)
{
ptr->Release();
ptr = nullptr;
}
}
用法示例:
IDirect3DDevice9 *pD3DDevice = NULL;
d3d->CreateDevice(..., &pD3DDevice);
SafeRelease(pD3DDevice);
您可能inline
如果你想要这个功能。
+1。使用'*&'的模板比我最初的尝试和金属建议更方便! –
你可以使用一个模板:
template<class DXInterface>
void SafeRelease(DXInterface **ppInterface) {
if(*ppInterface) {
(*ppInterface)->Release();
(*ppInterface) = nullptr;
}
}
你也可以使用一个std ::的unique_ptr或std :: shared_ptr的自动清理:
#include <memory>
#include <iostream>
struct Releaser {
template<class DXInterface>
void operator()(DXInterface *pInterface) const {
if(pInterface) {
pInterface->Release();
}
}
};
// For illustrative purposes only (supplied in DX9 headers)
struct IDirect3DSurface9 { void Release() { std::cout << "Released surface\n";} };
struct IDirect3DTexture9 { void Release() { std::cout << "Released texture\n";} };
void DX9CreateSurface(IDirect3DSurface9** surface)
{
*surface = new IDirect3DSurface9();
}
void DX9CreateTexture(IDirect3DTexture9** texture)
{
*texture = new IDirect3DTexture9();
}
// Your factory functions
IDirect3DSurface9* createSurface(/*init params go here*/)
{
IDirect3DSurface9* surface;
DX9CreateSurface(&surface);
return surface;
}
IDirect3DTexture9* createTexture(/*init params go here*/)
{
IDirect3DTexture9* texture;
DX9CreateTexture(&texture);
return texture;
}
int main()
{
typedef std::unique_ptr<IDirect3DSurface9, Releaser> SurfacePtr;
typedef std::unique_ptr<IDirect3DTexture9, Releaser> TexturePtr;
SurfacePtr surface(createSurface());
TexturePtr texture(createTexture());
// ... use surface and texture here
// Automatically released here when their lifetimes ends.
}
注意,他们使用相同的释放器,并注意到对surface.reset()的调用也会释放该接口,并将unique_ptr中的指针设置为null以引导。这两个对象可以是你的类的成员,而不是main()中的对象。
我在做什么在这里错了吗?
我只是有同样的问题,也为COM SafeRelease
。所以这里有云:
void SafeRelease(IUnknown **ppInterface)
...
IDirect3DSurface9 * mySurface = new ...
...
SafeRelease(&mySurface);
IDirect3DSurface9 *
,凭借继承的,可以转换为IUnknown *
。 但是,违反直觉,IDirect3DSurface9 **
不能转换为IUnknown **
。 如果允许,那里面你SafeRelease(IUnknown**)
,你可以做到以下几点:
// obtain a pointer to an instance of some random subinterface of IUnknown
*ppInterface = pMyRamdomComInterfacePointer;
这样,我们会保存一个指向一些随机IUnknown
衍生物指针IDirect3DSurface9
。这会违反C++类型的系统。这就是为什么铸造任何其他类型,但T**
到T**
是不允许的。换句话说,T**
类型的变量只能分配一个ppT
,而不是一个ppSomeSubytpeOfT
(一种T**
的值)。
比较这一个:How come a pointer to a derived class cannot be passed to a function expecting a reference to a pointer to the base class?这一个:Casting double pointers of base classes。
对于COM SafeRelease
,无论是模板(如建议在这里)或宏会做。
是否有创建这样一个函数的原因,而不是使用'ComPtr'? – Duncan