应该是这样的:当组件被聚合的时候,在它的QI中是直接调用外部组件的QI;而外部组件在QI内部组件的接口时是应该显式地调用内部组件的NondelegatingQueryInterface。《COM原理和应用》和《Inside COM》在讲到聚合时都是用这种方法来实现聚合的,但是ATL应该是用另一种方式来实现聚合的。虽然实现的方式不同,但是原理都是一样的。

解决方案 »

  1.   

    根据COM规范第0.9版中关于聚合的机制的论述中的第5点:当外部组件查询内部组件实现的接口时,外部组件是调用内部组件的非代理IUnknown的QI进行查询的。所以根据规范,内部组件的非代理IUnknown是不可避免地要被外部组件知道的。
      

  2.   

    to luxyi() :
     那么,书上的QueryInterface是NondelegatingQueryInterface的误笔了?
     外部组件调用内部组件的非代理IUnknown的QI进行查询的并不能说明内部组件的非代理IUnknown一定要暴露给客户,可以通过代理IUnknown来传递。
    如果com真像你说的,那么com真的有点不太完美了。无论组件是否被聚合,都只能通过QueryInterface得到接口。
    inside com中说得很清楚,P155上,被聚合的组件的客户永远都不会获得内部组件的非代理接口指针。
    大家继续讨论啊
      

  3.   

    我问了潘爱民老师,他的回答如下:
    我曾经用下面的类比来讲述过这个问题,看是否有助于你的理解。假设有两个二进制结构一样的vtable
    class Vtable1{
    virtual void __stdcall Method1(int, int) = 0;
    virtual void __stdcall Method2(int) = 0;
    };
    class Vtable2{
    virtual void __stdcall Operator1(int, int) = 0;
    virtual void __stdcall Operator2(int) = 0;
    };假设某段程序实现了其中之一
    class CMyObject : public Vtable1{
    ……
    virtual void __stdcall Method1(int, int);
    virtual void __stdcall Method2(int);
    };客户的用法
    实例化CMyObject :
    Vtable1 *p1 = CreateObject(...);
    代码片断1:
    p1->Method1(a, b);
    代码片断1:
    Vtable2 *p2 = (Vtable2 *)p1;
    p2->Operator1(a, b);
    这两段代码调用的是同一个方法,这里的要点是“指针类型并不重要,vtable才决定了
    内部方法的功能”。
    潘爱民谢谢大家的关注     
                                                    liu_feng_fly
      

  4.   

    呵呵,你可以看到右边有一竖排的EDIT,你可以在里面填上你要给这个家伙的分数,所有的分数不要超过你这个问题的给分,在页面的右上,你可以看到密码,填写密码,点击给分.OK:)