请高手讲解一下com中的包容与聚合,我在看vc技术内幕,这地方看的有点不明白.
解决方案 »
- ActvieX插件退出时卡死
- VC读取excel文件出错!请教各位!(俺实在看不出来了)
- ATL 中怎样才可以让其中一个对象做为另外一个对象的参数
- 在对话框编程时,利用双缓冲技术。消除了背景更新时背景的闪烁,但对话框上面的控件按钮,文本框等等却怎么在闪烁呢!
- 修改菜单字体,快键盘没办法弄
- 我认为是一个奇怪的问题,请教一下~~
- ·#¥%……—*请教一个结构体收发问题!
- 怎样在 NTFS 格式的硬盘上创建 EVERYONE 完全控制属性的目录~~~谢谢~~
- 兄弟在vc6上编译unicode的时候,系统找不到mfc43ud.lib,该从哪里找?
- 为什么有时候工程的资源文件不能打开?
- 请问:实现类似photoshop中的工具栏是不是用CToolBar
- 怎样生成一个CObject的一个派生类?
包含很简单:
struct OBJECT
{
long SomeThing;
};
struct CONTAINER
{
OBJECT Object;
};
就说CONTAINER这个结构包含了OBJECT这个结构,既在C中我们就大量使用了包含这个技术。
再如:
class CEmail
{
CStringW m_ShowName; // 显示名称
CStringW m_Add; // 装Email地址
};
CEmail email;
则说email通过包含而重用了两个CStringW对象聚合不常见,所以容易昏
class A
{
// 操作
public:
void A();
void AA();// 成员变量
private:
...
};
class B
{
// 操作
public:
void B();
void A() { m_A.A(); }
void AA() { m_A.AA(); }// 成员变量
private:
...
A m_A;
};
就说B聚合了A,如果
B g_B;
就说g_B通过聚合而重用了g_B.m_A,即是说聚合表示伪装,它让外界看起来它支持A()和AA(),实际它不支持,而是在内部秘密的要挟m_A来帮它完成任务,之所以被认为聚合,因为它将两个的类的功能合在了一个类中。与包容的区别就是包容不会暴露被重用的接口(即A(),AA())。
如果你仔细看过书,会发现书上将我上面说的聚合称作包容。不一样,我上面那种其实是静态聚合,既聚合的功能不能动态改变(要变就得重编代码),下面是COM中用到的聚合,是动态聚合
class C : public IUnknown
{
// 构造
public:
C( IUnknown *pUnk ) : m_pUnk( pUnk )
{
}// 其他重载IUnknown的成员
// 成员变量
private:
IUnknown *m_pUnk;
};
这样,C就动态聚合了从构造函数传入的m_pUnk的接口(既C现在对外宣称支持m_pUnk所指之对象所支持的接口),这通过QueryInterface来实现
HRESULT C::QueryInterface( REFIID iid, void **pVoid )
{
if( iid == IID_IUnknown )
*pVoid = static_cast< IUnknown* >( this );
else
if( m_pUnk && SUCCEEDED( m_pUnk->QueryInterface( iid, pVoid ) ) )
return S_OK;
else
return E_FAIL; return S_OK;
}
此时,可以写
extern IDispatch *g_pDisp;
C g_C( g_pDisp );
IDispatch *g_pD = NULL;
HRESULT hr =
g_C.QueryInterface( IID_IDispatch, reinterpret_cast< void** >( &g_pD ) );
ASSERT( SUCCEEDED( hr ) ); // g_C也支持IDispatch*,
// 而实现C时根本不知道有IDispatch这么一个东西因此,不是随便的QueryInterface的实现都可支持聚合的,所以ATL的向导同意你在实现COM对象时选择是否支持聚合。注意,这里应该说成被聚合才对,即选了选项后生成的COM对象将可以被别的COM对象(可以是不支持聚合的对象)聚合。
COM中的许多地方都用到聚合,如代理/占位程序中。