由于CreateInstance过程中需要调用FinalConstruct,用户很容易忘记,所以ATL提供了Creator类,这些类提供了一个静态函数
static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv);
CComCreator
template <class T1> class CComCreator { public: static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv) { ATLASSERT(ppv != NULL); if (ppv == NULL) return E_POINTER; *ppv = NULL; HRESULT hRes = E_OUTOFMEMORY; T1* p = NULL; ATLTRY(p = new T1(pv)) if (p != NULL) { p->SetVoid(pv); p->InternalFinalConstructAddRef(); hRes = p->_AtlInitialConstruct(); if (SUCCEEDED(hRes)) hRes = p->FinalConstruct(); if (SUCCEEDED(hRes)) hRes = p->_AtlFinalConstruct(); p->InternalFinalConstructRelease(); if (hRes == S_OK) hRes = p->QueryInterface(riid, ppv); if (hRes != S_OK) delete p; } return hRes; } };
例子:
STDMETHODIMP CPenguinCO::CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppv) { typedef CComCreator< CComPolyObject<CPenguin> > PenguinPolyCreator; return PenguinPolyCreator::CreateInstance(pUnkOuter, riid, ppv); }
由于typedef在不同的地方可能会造成多重命名,所以一种合理的方法是:
class CPenguin : ... { public: ... typedef CComCreator< CComPolyObject<CPenguin> > _CreatorClass; };
STDMETHODIMP CAviary::CreatePenguin(IBird** ppbird) { return CPenguin::_CreatorClass::CreateInstance(0, IID_IBird, (void**)ppbird); }
在chapter5,可以使用CComCoClass:
template <class T, const CLSID* pclsid = &CLSID_NULL> class CComCoClass { public: ... template <class Q> static HRESULT CreateInstance(IUnknown* punkOuter, Q** pp) { return T::_CreatorClass::CreateInstance(punkOuter, __uuidof(Q), (void**) pp); } template <class Q> static HRESULT CreateInstance(Q** pp) { return T::_CreatorClass::CreateInstance(NULL, __uuidof(Q), (void**) pp); } };
这样,代码简化为:
class CPenguin : ..., public CComCoClass<CPenguin, &CLSID_Penguin>, ... {...};
STDMETHODIMP CAviary::CreatePenguin(IBird** ppbird) {
return CPenguin::CreateInstance(ppbird);
}
CComCreator2
这个类是为了支持standalone和aggregate 2种方式
template <class T1, class T2> class CComCreator2 { public: static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv) { ATLASSERT(*ppv == NULL); return (pv == NULL) ? T1::CreateInstance(NULL, riid, ppv) : T2::CreateInstance(pv, riid, ppv); } };
例如:
class CPenguin : ... { public: ... typedef CComCreator2< CComCreator< CComObject<CPenguin> >, CComCreator< CComAggObject<CPenguin> > > _CreatorClass; };
CComFailCreator
如果用户只准备实现standalone或者只准备实现aggregate,可以使用这个类来进行提示:
template <HRESULT hr> class CComFailCreator { public: static HRESULT WINAPI CreateInstance(void*, REFIID, LPVOID*) { return hr; } };
只实现standalone例子:
class CPenguin : ... {
public:
...
typedef CComCreator2< CComCreator< CComObject<CPenguin> >,
CComFailCreator<CLASS_E_NOAGGREGATION> >
_CreatorClass;
};
只实现aggregate例子:
class CPenguin : ... {
public:
...
typedef CComCreator2< CComFailCreator<E_FAIL>,
CComCreator< CComAggObject<CPenguin> > >
_CreatorClass;
};
和Creator有关的宏
#define DECLARE_POLY_AGGREGATABLE(x) public:\ typedef ATL::CComCreator< \ ATL::CComPolyObject< x > > _CreatorClass; #define DECLARE_AGGREGATABLE(x) public: \ typedef ATL::CComCreator2< \ ATL::CComCreator< ATL::CComObject< x > >, \ ATL::CComCreator< ATL::CComAggObject< x > > > \ _CreatorClass; #define DECLARE_NOT_AGGREGATABLE(x) public:\ typedef ATL::CComCreator2< \ ATL::CComCreator< ATL::CComObject< x > >, \ ATL::CComFailCreator<CLASS_E_NOAGGREGATION> > \ _CreatorClass; #define DECLARE_ONLY_AGGREGATABLE(x) public:\ typedef ATL::CComCreator2< \ ATL::CComFailCreator<E_FAIL>, \ ATL::CComCreator< ATL::CComAggObject< x > > > \ _CreatorClass;
上述都是为了定义_CreatorClass
例如:
class CPenguin : ... {
public:
...
DECLARE_AGGREGATABLE(CPenguin)
};
Macro | Standalone | Aggregation |
---|---|---|
DECLARE_AGGREGATABLE | CComObject | CComAggObject |
DECLARE_NOT_AGGREGATABLE | CComObject | |
DECLARE_ONLY_AGGREGATABLE | CComAggObject | |
DECLARE_POLY_AGGREGATABLE | CComPolyObject | CComPolyObject |
CreateInstance
static HRESULT WINAPI CComObject::CreateInstance(CComObject<Base>** pp); static HRESULT WINAPI CComAggObject::CreateInstance(IUnknown* puo, CComAggObject<contained>** pp); static HRESULT WINAPI CComPolyObject::CreateInstance(IUnknown* puo, CComPolyObject<contained>** pp);
这些静态函数并不使用Creator,而是按部就班的创建并且调用FinalConstruct,不同的是它们返回派生类的直接指针,例子:
STDMETHODIMP
CAviary::CreatePenguin(BSTR bstrName, long nWingspan,
IBird** ppbird) {
HRESULT hr;
CComObject<CPenguin>* pPenguin = 0;
hr = CComObject<CPenguin>::CreateInstance(&pPenguin);
if( SUCCEEDED(hr) ) {
pPenguin->AddRef();
pPenguin->Init(bstrName, nWingspan);
hr = pPenguin->QueryInterface(IID_IBird, (void**)ppbird);
pPenguin->Release();
}
return hr;
}
下列代码则是错误的:
STDMETHODIMP CAviary::CreatePenguin(BSTR bstrName, long nWingspan, IBird** ppbird) { HRESULT hr; hr = CPenguin::_CreatorClass::CreateInstance(0, IID_IBird, (void**)ppbird); if( SUCCEEDED(hr) ) { // Resist this instinct! CPenguin* pPenguin = (CPenguin*)(*ppbird); pPenguin->Init(bstrName, nWingspan); } return hr; }