在我的代码中有相当多的接口,我想在另一个方法中封装重复的Release
代码,而不是在宏中,因为这是C ++而我讨厌使用宏。我最初的尝试是编写一个方法,如
void SafeRelease(IUnknown **ppInterface) {
if(*ppInterface) {
(*ppInterface)->Release();
(*ppInterface) = nullptr;
}
}
然而,将此方法应用于IDirect3DSurface9 *
,例如与SafeRelease(&mySurface)
类似,错误IDirect3DSurface9 **
与IUnknown **
不兼容。
答案 0 :(得分:1)
这是我的方法:
template <typename T> void SafeRelease(T*& ptr)
{
if(ptr)
{
ptr->Release();
ptr = nullptr;
}
}
使用示例:
IDirect3DDevice9 *pD3DDevice = NULL;
d3d->CreateDevice(..., &pD3DDevice);
SafeRelease(pD3DDevice);
如果您愿意,可以inline
此功能。
答案 1 :(得分:0)
您可以使用模板:
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.
}
请注意,它们使用相同的Releaser,并注意对surface.reset()的调用也会释放该接口,并将unique_ptr中的指针设置为null以引导。这两个对象可以是您的类的成员,而不是main()中的对象。
答案 2 :(得分:0)
我在这做错了什么?
我也有同样的问题,也适用于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
(类型为T**
的值)而不是ppSomeSubytpeOfT
。
比较这个: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
,模板(如此处所示)或宏都可以。