如下,定义了一个CHello组件类。
class ATL_NO_VTABLE CHello :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CHello, &CLSID_Hello>,
public IDispatchImpl<IHello, &IID_IHello, &LIBID_netfeesrvLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
CHello()
{
}.....CComObject<CHello> 提供了IUnknown方法的真正实现。我想知道的是:ATL是如何将IDispatch中的方法(如:GetTypeInfo ...)按循序排在IUnknown方法(如:QuteryInterface ...)之后的?
class ATL_NO_VTABLE CHello :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CHello, &CLSID_Hello>,
public IDispatchImpl<IHello, &IID_IHello, &LIBID_netfeesrvLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
CHello()
{
}.....CComObject<CHello> 提供了IUnknown方法的真正实现。我想知道的是:ATL是如何将IDispatch中的方法(如:GetTypeInfo ...)按循序排在IUnknown方法(如:QuteryInterface ...)之后的?
//Base is the user's class that derives from CComObjectRoot and whatever
//interfaces the user wants to support on the object
template <class Base>
class CComObject : public Base
{
public:
typedef Base _BaseClass;
CComObject(void* = NULL) throw()
{
_pAtlModule->Lock();
}
// Set refcount to -(LONG_MAX/2) to protect destruction and
// also catch mismatched Release in debug builds
~CComObject() throw()
{
m_dwRef = -(LONG_MAX/2);
FinalRelease();
#ifdef _ATL_DEBUG_INTERFACES
_AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown());
#endif
_pAtlModule->Unlock();
}
//If InternalAddRef or InternalRelease is undefined then your class
//doesn't derive from CComObjectRoot
STDMETHOD_(ULONG, AddRef)() throw() {return InternalAddRef();}
STDMETHOD_(ULONG, Release)() throw()
{
ULONG l = InternalRelease();
if (l == 0)
delete this;
return l;
}
//if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP
STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw()
{return _InternalQueryInterface(iid, ppvObject);}
template <class Q>
HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp) throw()
{
return QueryInterface(__uuidof(Q), (void**)pp);
} static HRESULT WINAPI CreateInstance(CComObject<Base>** pp) throw();
};
IDispatch : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(
/* [out] */ UINT *pctinfo) = 0;
virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(
/* [in] */ UINT iTInfo,
/* [in] */ LCID lcid,
/* [out] */ ITypeInfo **ppTInfo) = 0;
virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(
/* [in] */ REFIID riid,
/* [size_is][in] */ LPOLESTR *rgszNames,
/* [in] */ UINT cNames,
/* [in] */ LCID lcid,
/* [size_is][out] */ DISPID *rgDispId) = 0;
virtual /* [local] */ HRESULT STDMETHODCALLTYPE Invoke(
/* [in] */ DISPID dispIdMember,
/* [in] */ REFIID riid,
/* [in] */ LCID lcid,
/* [in] */ WORD wFlags,
/* [out][in] */ DISPPARAMS *pDispParams,
/* [out] */ VARIANT *pVarResult,
/* [out] */ EXCEPINFO *pExcepInfo,
/* [out] */ UINT *puArgErr) = 0;
};
WORD wMinor = 0, class tihclass = CComTypeInfoHolder>
class ATL_NO_VTABLE IDispatchImpl : public T
{
public:
typedef tihclass _tihclass;
// IDispatch
STDMETHOD(GetTypeInfoCount)(UINT* pctinfo)
{
*pctinfo = 1;
return S_OK;
}
STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
{
return _tih.GetTypeInfo(itinfo, lcid, pptinfo);
}
STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
LCID lcid, DISPID* rgdispid)
{
return _tih.GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
}
STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid,
LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
return _tih.Invoke((IDispatch*)this, dispidMember, riid, lcid,
wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
}#ifdef _ATL_DLL_IMPL
// Do not cache type info if it is used in atl70.dll
IDispatchImpl() : _tih(piid, plibid, wMajor, wMinor)
{
}protected:
_tihclass _tih;
HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo)
{
return _tih.GetTI(lcid, ppInfo);
}#elseprotected:
static _tihclass _tih;
static HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo)
{
return _tih.GetTI(lcid, ppInfo);
}#endif};这里方法的顺序好像是对的,但我想知道,这些方法是如何按循序排在IUnknown方法(如:QuteryInterface ...)之后的?
IDispatch : public IUnknown
不是IDispatchImpl 决定的.
而你的接口通常都会从IDispatch 继承.那么你的接口提供的方法都在IDispatch之后而IDispatchImpl 和CComObject什么的都是提供具体的实现
接口的继承关系都在idl文件中定义
IDispatchImpl 实现IDisopatch方法.
CComObject 实现IUnknown方法。
CComObject 实现IUnknown方法。
呵呵,是这样的