not inside alt.chm .and the book named windows 2000 programming unleashed .it explain clearly.
 hehehehehe.....

解决方案 »

  1.   

    to sober:Thanks.又要买书, 5555...555...
    总觉得入门非常难,上面那几个疙瘩真让我伤脑筋。各位老大快快出手吧!!!
      

  2.   

    sigh,CSDN无人哪??? 可悲可叹!!! COM高手,你在哪里呀?!
      

  3.   

    sigh,sigh...兄弟们,没COM高手,咱们就发几句牢骚吧!发一句牢骚我给十分!
      

  4.   

    这么好的得分机会都没人要了吗?爱好COM的兄弟们快来捧捧场!
      

  5.   

    哇,你这个问题好大呀,不多给点分吗,380?
    1.
    不管是什么线程模型,如果你的COM Object访问全局变量,或者类有静态数据成员,统统要加同步机制的。
    对于MTA(Free),则类的所有数据成员也要加同步机制。
    2.
    有虚拟函数的C++类,它的每个实例都有一个指针,称为VPTR,它指向一个称为VTBL的虚拟函数表,该表存放该类的虚拟函数的函数地址。当你调用某一个类的实例的虚拟函数时,编译器生成的代码由类实例的VPTR找到VTBL,从而找到该类实现的虚拟函数版本的地址,从而调用正确的重载函数。
    ATL中,你定义的对象类,假设叫CMyObject,是不能实例化的,因为它是抽象类,有纯虚函数未被实例化,这些纯虚函数是什么呢?是与AddRef、Release有关的函数。这些函数由谁实例化呢?CComObject<CMyObject>或CComAggObject<CMyObject>。你定义的类CMyObject的实例,它有一个若干字节的VTBL。而类CComObject<CMyObject>的实例,它又有自己的VTBL,这个VTBL有它实现的AddRef和Release等表项,也有CMyObject中有的很多虚拟函数地址。显然后者是与CMyObject的VTBL占有的字节重复的。这些字节能不能省去呢?如果不加ATL_NO_VTABLE,不行。因为你的程序中显然要引用CMyObject的函数,包括虚函数,所以CMyObject的VTBL必须保留。
    想想看,你的CMyObject是从许多ATL类中派生的,它们都有很多虚函数,因此有很多VTBL,这要浪费许多字节。而ATL的设计意图,就是用精练的代码编写出高效的COM对象。ATL_NO_VTABLE将使CMyObject类不生成VTBL,而在派生树的最后一级(CComObject)才生成。
    3.
    Aggregation是将一个现成的组件对象A包装在一个新组件B中,使得外界看到的B也有A的接口而感觉不到A的存在。但需要处理的问题远没原理那么简单。支持Aggregation的对象类用CComAggObject实例化。
    Tear-Off是这样的接口,当生成COM Object时,并不生成该接口的VTBL(接口在C++看来就是一个全是纯虚函数的类),只当用户用QueryInterface要求该接口时才生成。当该接口不在被使用时,VTBL被释放。
    Aggregation和Tear-Off是各自独立的技术,不存在直接关系。
    4.
    Class A: public IDispatchImpl
    {
    public:
    integer x1;
    integer x2;
    };
    A a;offsetof(x1)的作用就象a.x1,不过offsetof的参数经常是一个类的基类,例如:
    class B :public A;
    offsetof(A)将返回A在B中的VPTR地址,有了它你就能找到VTBL,特别当A是个接口实现时,通过它你能访问A接口的方法实现。C++在X86平台的实现中,VPTR总是处在类的实例中的第一个字节。offsetof在我们编程序时很少用到,它是ATL在内部实现是经常用的。你问的这个问题很深啊,你不象是ATL新手啊?呵呵,你可让我费了不少时间写这么多东西,如果你觉得有道理的话,别忘了给我加分啊!
      

  6.   

    to horris: 我代表所有COM新手向你致敬!分数在买单时一并加上.谈谈我的疑问:    搞这么多的线程模型,只是因为性能的原因吗?还是有其他方面的考虑?线程模型是由 客户端CoInitialize(或CoInitializeEx)初始化方式和COM Object使用的线程模型 共同决定的吗?假如不一致会怎样?    #define _ATL_PACKING 8
        #define offsetofclass(base, derived) ((DWORD)(static_cast<base*>((derived*)_ATL_PACKING))-_ATL_PACKING)
        我怎么算来算去offsetofclass结果都是零呢? static_cast<base*>, dynamic_cast<base*>与(base*)ptr强制转换有什么区别,仅仅只是为了在运行时进行类型安全校验吗?欢迎COM高手发表高见,只要跟COM相关的就行。
      

  7.   

    插一句:
      请注意Aggregation和继承的不同观念,这是两种不同的重用概念和方法。
      

  8.   

    edyang大哥,不要那么谦虚嘛.快来,快来!
      

  9.   

    COM的线程模型并不多嘛,说到底只有STA和MTA之分。如果client和Server所用的线程模型不一样,则COM系统就要做Marshalling,这时会有一些开销。out-of-process server总是要求Marshalling的。
    如果你的类有多个基类,则你就会看出offsetof的作用。
      

  10.   

    我也是刚刚入门,还不能自由的阐述这些问题,但可以谈谈我的理解,可能对大家是误导,请监督。
    1、线程模型
    既然不要抄写 Inside ATL,我就从 Inside COM 上比葫芦画瓢吧!
    COM 的消息管理和同步机制利用的是大家熟悉的 WIN32 线程管理机制,特别与线程和窗口的关系类似。一个线程可以拥有几个窗口,但是一个窗口只能同时被一个窗口所拥有。所以,尽管消息是随机的,不同步的,但是 Windows 发给每个线程的消息后,每个窗口所接受到的信息是按顺序的,同步的。
    一个 Apartment 相当于一个线程,它有一个消息循环队列负责消息的分发,在同一个 Apartment 中的 COM 对象不必担心会同时(呵呵,意思是还没有处理完一个请求就被 Windows 打断了,再去处理另一个请求)收到两个调用请求,所以不会出现同步问题。一个 Apartment 的建立和销毁分别由 CoInitialize 和 CoUninitialize 来完成,所以每个要调用 COM 服务的线程必须要调用这两个 API。创建一个 Apartment 的线程拥有这个 Apartment,叫做 Apartment Thread。
    这些工作都是由 COM 服务提供的,组件开发者不用去实现同步代码。
    与 Apartment 模型相对比,Free Thread 模型就是指一个 COM 组件不被任何线程所拥有,可以在任何时候被任何线程调用。即,COM 服务不再创建一些机制(如,一个不可见的消息队列 - Apartment)用来保证 COM 组件的同步调用问题。
    但是,并不意味着 Apartment Thread 模型所创建的组件就丝毫不用担心自己的共有数据(如,全局变量),有以下问题要考虑:
    1、程内组件必须考虑 DllGetClassObject/DllCanUnloadNow 是否因该实现线程同步;
    2、可能需要线程安全的 Class Factory;
    其它还要涉及到 Marshaling 的问题,本人只有个大概概念,所以不再讨论。
      

  11.   

    2、这个其实很好理解,下面是 ATLDEF.H 中的片段:
    #ifdef _ATL_DISABLE_NO_VTABLE
    #define ATL_NO_VTABLE
    #else
    #define ATL_NO_VTABLE __declspec(novtable)
    #endif
    也就是说,在可以使用 ATL_NO_VTABLE 的功能的情况下,ATL_NO_VTABLE 相当于 __declspec(novtable),MSDN 上说得很明白(Sorry :-(),因为 COM 接口在 C++ 的类定义必须是纯虚类,不可被实例化,只能被继承,所以专门用来存储虚函数指针的 vtable ( vfptr) 就没有任何用处。禁止编译器和连接器生成没有作用的 vtable,可以大大减小最终代码的大小。
      

  12.   

    3、因为 COM 是一组如何实现二进制级上的代码重用,所以传统的语言级别上的代码重用机制就不能用。Aggregation 是 COM 实现代码重用的一种方法,另外一种是 Containment。原理很简单,在此不再多说。Tear-off 没研究过,更没用过,好像比较高级一些,具体请看相关书籍,如:Inide ATL, Inside COM。呵呵,不要向我仍臭鸡蛋
      

  13.   

    4、请看 http://msdn.microsoft.com/library/default.asp?URL=/library/welcome/dsmsdn/deep05182000.htm
      

  14.   

      继承是原代码级别实现的,而聚合与包容是COM中独有的在二进制上实现代码重用的方法。 
      我觉得最重要得模型是APARTMENT,它的实现使得多线程访问同一个实例提供了简化的方法(好象是插入STUB串形访问实例记不清楚了) 
      推荐一本好书《COM原理与应用》,关于线程模型与COM重用都有比较详细的解说。不过给的例子好象是用MFC实现的,但这应该不是问题。
      

  15.   

    果然都是COM高手. 收益非浅...收益非浅...收益非浅...!!!
      

  16.   

    我推荐一本好书,《ATL Internals》,Brent Rector&Chris Sells,Addison-Wesley Longman Press,1999。我是在图书馆借到的,还没见过中译本,即便有,我建议也不要看,不可多得的好书。
      

  17.   

    看着幸福的horris,bgsn的口水流了一米长......
    (bgsn用充满期盼的目光看着horris说)有没有电子版?给兄弟我MAIL一份如何?
      

  18.   

    请教一下horris和edyang大虾,atl做com组件的时候,CComObject的实例化在什么地方??
      

  19.   

    to sunlet:
    CComObject的实例化过程是在client调CoCreateInstance时,是由ATL实现的CComCoClass(你的每个对象类几乎都从它派生)实现的。一般地,不用关心这个过程。
    to bgsn:
    非常遗憾, 我不知道有没有电子版。 你可以去www.awl.com/cseng看看, 这是Addison-Wesley Longman Press.的主页, 上面可以下载此书所附的源代码。