1 关于句柄类
句柄类也完全可以实现:接口和实现的分离,Don Box在书中也讲到这一点,但是vc开发com组件好像没有采用句柄类的,像MFC采用的嵌套类技术,ATL采用的抽象基类的多继承,模版技术,为什么句柄类没有得到应用???谁能给解释解释2关于嵌套类
com的本质是一个接口与实现分离的C++类,如何实现接口和实现的分离是一个问题,通过用纯虚类做为基类来实现接口和实现的分离,我可以理解,但是嵌套类怎么能实现接口和实现的分离,那位老大能给解释一下??
纯虚类可以作为接口,是因为纯虚类不包含数据成员,只是通过虚函数表可以提供接口函数的入口地址
但是嵌套类就不同了,它有自己的数据成员,比如CCmdTarget类,ccmdtarget是如何来体现二进制的接口协议的呢?欢迎高手参加讨论,如果你们能将嵌套类实现com二进制协议接口讲述的很清楚的话,我开贴另谢
句柄类也完全可以实现:接口和实现的分离,Don Box在书中也讲到这一点,但是vc开发com组件好像没有采用句柄类的,像MFC采用的嵌套类技术,ATL采用的抽象基类的多继承,模版技术,为什么句柄类没有得到应用???谁能给解释解释2关于嵌套类
com的本质是一个接口与实现分离的C++类,如何实现接口和实现的分离是一个问题,通过用纯虚类做为基类来实现接口和实现的分离,我可以理解,但是嵌套类怎么能实现接口和实现的分离,那位老大能给解释一下??
纯虚类可以作为接口,是因为纯虚类不包含数据成员,只是通过虚函数表可以提供接口函数的入口地址
但是嵌套类就不同了,它有自己的数据成员,比如CCmdTarget类,ccmdtarget是如何来体现二进制的接口协议的呢?欢迎高手参加讨论,如果你们能将嵌套类实现com二进制协议接口讲述的很清楚的话,我开贴另谢
解决方案 »
- 动态创建的控件如何响应事件。
- Error 4 error LNK2019: unresolved external symbol __imp__GetResultData refer
- MSDN中Com/Win32的示例在Platform/WindowsSDK吗?
- 仿QQ界面切换源码下载
- 求:如何知道客户端dll控件的版本号?
- 基于对话框的程序,请问如何在主窗口显示后再弹出一个对话框?
- IP层网关
- 求救:为何在NT服务程序打开数据源时总是发生异常?真奇怪
- 怎樣實現BlueScreenOfDeath 來顯示自己設置的信息(主要是文本)
- 史前第一大冤案!!
- 用ATL写的一个Dll,在DLL中如何调用一个EXE的函数或功能呢。请指教。谢谢!
- 升级platform sdk的问题
class CCmdTarget : public CObject
#else
class AFX_NOVTABLE CCmdTarget : public CObject
#endif
{
DECLARE_DYNAMIC(CCmdTarget)
protected:public:
// Constructors
CCmdTarget();// Attributes
LPDISPATCH GetIDispatch(BOOL bAddRef);
// retrieve IDispatch part of CCmdTarget
static CCmdTarget* PASCAL FromIDispatch(LPDISPATCH lpDispatch);
// map LPDISPATCH back to CCmdTarget* (inverse of GetIDispatch)
BOOL IsResultExpected();
// returns TRUE if automation function should return a value// Operations
void EnableAutomation();
// call in constructor to wire up IDispatch
void EnableConnections();
// call in constructor to wire up IConnectionPointContainer void BeginWaitCursor();
void EndWaitCursor();
void RestoreWaitCursor(); // call after messagebox#ifndef _AFX_NO_OLE_SUPPORT
// dispatch OLE verbs through the message map
BOOL EnumOleVerbs(LPENUMOLEVERB* ppenumOleVerb);
BOOL DoOleVerb(LONG iVerb, LPMSG lpMsg, HWND hWndParent, LPCRECT lpRect);
#endif// Overridables
// route and dispatch standard command message types
// (more sophisticated than OnCommand)
virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo);#ifndef _AFX_NO_OLE_SUPPORT
// called when last OLE reference is released
virtual void OnFinalRelease();
#endif#ifndef _AFX_NO_OLE_SUPPORT
// called before dispatching to an automation handler function
virtual BOOL IsInvokeAllowed(DISPID dispid);
#endif#ifndef _AFX_NO_OLE_SUPPORT
// support for OLE type libraries
void EnableTypeLib();
HRESULT GetTypeInfoOfGuid(LCID lcid, const GUID& guid,
LPTYPEINFO* ppTypeInfo);
virtual BOOL GetDispatchIID(IID* pIID);
virtual UINT GetTypeInfoCount();
virtual CTypeLibCache* GetTypeLibCache();
virtual HRESULT GetTypeLib(LCID lcid, LPTYPELIB* ppTypeLib);
#endif// Implementation
public:
virtual ~CCmdTarget();
#ifdef _DEBUG
virtual void Dump(CDumpContext& dc) const;
virtual void AssertValid() const;
#endif
#ifndef _AFX_NO_OLE_SUPPORT
void GetNotSupported();
void SetNotSupported();
#endifprotected:
friend class CView; CView* GetRoutingView();
CFrameWnd* GetRoutingFrame();
static CView* PASCAL GetRoutingView_();
static CFrameWnd* PASCAL GetRoutingFrame_();
DECLARE_MESSAGE_MAP() // base class - no {{ }} macros#ifndef _AFX_NO_DOCOBJECT_SUPPORT
DECLARE_OLECMD_MAP()
friend class COleCmdUI;
#endif#ifndef _AFX_NO_OLE_SUPPORT
DECLARE_DISPATCH_MAP()
DECLARE_CONNECTION_MAP()
DECLARE_INTERFACE_MAP()#ifndef _AFX_NO_OCC_SUPPORT
DECLARE_EVENTSINK_MAP()
#endif // !_AFX_NO_OCC_SUPPORT // OLE interface map implementation
public:
// data used when CCmdTarget is made OLE aware
long m_dwRef;
LPUNKNOWN m_pOuterUnknown; // external controlling unknown if != NULL
DWORD m_xInnerUnknown; // place-holder for inner controlling unknownpublic:
// advanced operations
void EnableAggregation(); // call to enable aggregation
void ExternalDisconnect(); // forcibly disconnect
LPUNKNOWN GetControllingUnknown();
// get controlling IUnknown for aggregate creation // these versions do not delegate to m_pOuterUnknown
DWORD InternalQueryInterface(const void*, LPVOID* ppvObj);
DWORD InternalAddRef();
DWORD InternalRelease();
// these versions delegate to m_pOuterUnknown
DWORD ExternalQueryInterface(const void*, LPVOID* ppvObj);
DWORD ExternalAddRef();
DWORD ExternalRelease(); // implementation helpers
LPUNKNOWN GetInterface(const void*);
LPUNKNOWN QueryAggregates(const void*); // advanced overrideables for implementation
virtual BOOL OnCreateAggregates();
virtual LPUNKNOWN GetInterfaceHook(const void*); // OLE automation implementation
protected:
struct XDispatch
{
DWORD m_vtbl; // place-holder for IDispatch vtable
#ifndef _AFX_NO_NESTED_DERIVATION
size_t m_nOffset;
#endif
} m_xDispatch;
BOOL m_bResultExpected; // member variable-based properties
void GetStandardProp(const AFX_DISPMAP_ENTRY* pEntry,
VARIANT* pvarResult, UINT* puArgErr);
SCODE SetStandardProp(const AFX_DISPMAP_ENTRY* pEntry,
DISPPARAMS* pDispParams, UINT* puArgErr); // DISPID to dispatch map lookup
static UINT PASCAL GetEntryCount(const AFX_DISPMAP* pDispMap);
const AFX_DISPMAP_ENTRY* PASCAL GetDispEntry(LONG memid);
static LONG PASCAL MemberIDFromName(const AFX_DISPMAP* pDispMap, LPCTSTR lpszName); // helpers for member function calling implementation
static UINT PASCAL GetStackSize(const BYTE* pbParams, VARTYPE vtResult);
#ifdef _PPC_
SCODE PushStackArgs(BYTE* pStack, const BYTE* pbParams,
void* pResult, VARTYPE vtResult, DISPPARAMS* pDispParams,
UINT* puArgErr, VARIANT* rgTempVars, UINT nSizeArgs);
#else
SCODE PushStackArgs(BYTE* pStack, const BYTE* pbParams,
void* pResult, VARTYPE vtResult, DISPPARAMS* pDispParams,
UINT* puArgErr, VARIANT* rgTempVars);
#endif
SCODE CallMemberFunc(const AFX_DISPMAP_ENTRY* pEntry, WORD wFlags,
VARIANT* pvarResult, DISPPARAMS* pDispParams, UINT* puArgErr); friend class COleDispatchImpl;#ifndef _AFX_NO_OCC_SUPPORT
public:
// OLE event sink implementation
BOOL OnEvent(UINT idCtrl, AFX_EVENT* pEvent,
AFX_CMDHANDLERINFO* pHandlerInfo);
protected:
const AFX_EVENTSINKMAP_ENTRY* PASCAL GetEventSinkEntry(UINT idCtrl,
AFX_EVENT* pEvent);
#endif // !_AFX_NO_OCC_SUPPORT // OLE connection implementation
struct XConnPtContainer
{
DWORD m_vtbl; // place-holder for IConnectionPointContainer vtable
#ifndef _AFX_NO_NESTED_DERIVATION
size_t m_nOffset;
#endif
} m_xConnPtContainer;#ifdef _AFXDLL
AFX_MODULE_STATE* m_pModuleState;
friend class CInnerUnknown;
friend UINT APIENTRY _AfxThreadEntry(void* pParam);
#endif virtual BOOL GetExtraConnectionPoints(CPtrArray* pConnPoints);
virtual LPCONNECTIONPOINT GetConnectionHook(const IID& iid); friend class COleConnPtContainer;#endif //!_AFX_NO_OLE_SUPPORT
};
3包装类
我们知道在调用com组件的时候,一般都有三种方法,其中一种就是通过com组件的tlb库生成包装类,谁能给解释一下,为什么要通过包装类调用com?why
"包含虚拟函数的C++对象都将包含一个指向虚函数表的指针,这种结构符合COM接口规范。"
这句话怎么理解
可以理解为:所有具有虚函数的类的声明,都可以作为com组件的接口,这么理解对吗?
还是只有具有纯虚函数的抽象基类才可以作为com的接口?我一直认为,只有抽象基类可以作为接口,因为抽象基类没法声明对象,只能通过派生类来声明对象,抽象基类只是提供了接口函数的入口地址,ATL一般都是以抽象基类作为接口的,然后通过多继承实现多接口,但是MFC是从CCmdTarget类继承过来的,我看了ccmdtarget类的定义了,它不是抽象基类,那它是如何实现接口的?当然ccmdtarget是通过嵌套类对象和父类指针的偏移表来实现多接口的,这个我可以理解,我现在不明白的就是从ccmdtartget派生出来的类怎么可以实现二进制接口了?它又不是抽象基类,如果ccmdtarget添加了数据成员了,它的对象的大小肯定会发生变化,请继续讨论
俺也是才学习COM.大致和楼上的理解差不多...
观注.......
从接口继承的类是接口实现类,再从这个类继承的类也是实现类,同样嵌套了该类的类也是实现类。
class A:public IXXX {...}
class B:public A {...}
class C {
...
class C1 : public IXXX {...}
...
}
以上A、B、C都是接口实现类(COM对象),因为它们都有一个共同的特点,就是其类实例都拥有一个特殊的成员变量-IXXX的vptr和都拥有一个虚函数表。
C就是使用嵌套类的情况,ccmdtarget就是这种类。
本来早上来想结贴的,看楼上还有很多人不明白,希望继续讨论,同时也给 小星星,和月吻长河推荐com本质论,这本书,里面对com讲的很透彻,我这里有电子版,如果需要,请联系我,希望麦猪接口的内存表示形式给大家讲一下,如果这个周末没有事情的话,我会将我对com的理解写出来给大家贴出来,下周结贴
呵呵...正在学习..希望大家多交流一下心得.
(1) COM组件实际上是一个C++类,而接口都是纯虚类。组件从接口派生而来。我们可以简单的用纯粹的C++的语法形式来描述COM是个什么东西:
class IObject
{
public:
virtual Function1(...) = 0;
virtual Function2(...) = 0;
....
};
class MyObject : public IObject
{
public:
virtual Function1(...){...}
virtual Function2(...){...}
....
};
看清楚了吗?IObject就是我们常说的接口,MyObject就是所谓的COM组件。切记切记接口都是纯虚类,它所包含的函数都是纯虚函数,而且它没有成员变量。而COM组件就是从这些纯虚类继承下来的派生类,它实现了这些虚函数,仅此而已。从上面也可以看出,COM组件是以 C++为基础的,特别重要的是虚函数和多态性的概念,COM中所有函数都是虚函数,都必须通过虚函数表VTable来调用,这一点是无比重要的,必需时刻牢记在心。
嘿嘿~~
COM真的有这么简单就好了。
个人觉得COM为了跨越语言界限付出了很重的代价,加上跨进程、线程间对象
引用让人觉得学习COM只有“难”一个字。