创建一个com组件的对象有多种办法,每种办法得到的都是一个指向获得的特定接口的指针。就向c++的对象一样,每个com组件对象都有自己的一份数据拷贝,但是却共用一份的函数拷贝。因此,对于同一个com组件,创建的每一个对象获得的都应该是指向同一个内存中虚函数表中,那么得到这样的指针以后,我怎么针对特定的对象进行操作呢?或者说,创建一个com对象后,它的this指针放在哪里,我怎么去获得呢?

解决方案 »

  1.   

    如果使用com,
    你应该知道只能对接口操作,而不能对对象操作啊。
      

  2.   

    如果比较了解COM了,请看看《COM本质论》如果不了解先看《COM原理与应用》如果C++不是很精,请看《深度探索C++对象模型》
      

  3.   

    返回给你的接口指针不就是this指针吗?
      

  4.   

    对于C++实现的COM对象,接口指针不一定是this指针。
    COM是和语言无关的,没有this这个概念
      

  5.   

    this具体在哪要视COM组件是如何实现的,如果使用多重继承的形式(ATL就使用这种形式),那么接口指针就是this了;如果使用嵌套类的形式(MFC使用这种形式),需要自己对传进来的this(传进成员函数的this)做些变换,MFC专门提供了宏METHOD_PROLOGUE以进行这种变换,前提是用MFC的方式实现接口(即通过宏BEGIN_INTERFACE_PART和END_INTERFACE_PART来实现嵌套类)
      

  6.   

    To:jiangsheng(蒋晟.Net)对于C++实现的COM对象 到底有没有this指针???
      

  7.   

    COM规范里面肯定是没有this指针这个概念的.但是由于你开发的环境是C++,所以就有了this指针.我认为他的功能可以被别的取代.
      

  8.   

    STDAPI CoCreateInstance(
      REFCLSID rclsid,
      LPUNKNOWN pUnkOuter,
      DWORD dwClsContext,
      REFIID riid,
      LPVOID * ppv
    );HRESULT QueryInterface(
      LPUNKNOWN ps,      
      const IID & riid,  
      void **ppvObj       
    );
    LPVOID * ppv和void **ppvObj 带回了对象指针,所以*ppvObj和ppv大概就是你要的this指针.
      

  9.   

    To:zixu(子旭) LPVOID * ppv和void **ppvObj 均是接口的指针,并不是对象的指针,也不是this指针
      

  10.   

    To:lop5712(LOP) 如果像你说的使用多重继承的形式(ATL就使用这种形式),那么接口指针就是this了。
    这么说,N 个接口指针也是this 的话,N 个接口指针 的值也是相等的,但事实上同一个COM对象不同的接口指针的值是不一样的,所以说接口指针并不是this指针。
      

  11.   

    COM的对象根本就是不可见的.你只是可以通过接口来感知它的存在.我想根本不存在什么对象指针.只是依靠CLSID来找到它.LPVOID * ppv和void **ppvObj 均是接口的指针也是this指针.你要是把接口类,当成一个普通的类.那么它就是通过this调用的.
      

  12.   

    我昨天接下去看书的时候,觉得是不是这样的,比如cocreateinstance得到的一个ppv,它应该是指向一个接口数据结构,这个结构里面可能包含了最少两个指针,一个指向它的虚函数表入口地址,另一个就是指向对象自己的数据成员地址,也就是c++里的this指针了。这样,如果是不同的com对象,这个ppv当然就不一样了,但是对于同一个组件类,对象指针里的第一个指针又都是一样的。
      

  13.   

    你就不考虑用其他语言也可以编写COM组件?那里可没什么this这一说
      

  14.   

    不管叫不叫this,我想总归每个对象都有自己的数据,创建了一个对象以后,这些数据的存放地址总要被保存着的,虽然用户不能看见也不应该知道,但是每个函数的操作都是针对特定的对象,特定的数据,不知道数据的地址,那还谈何操作呢?
      

  15.   

    this指针是什么?就是com对象的一个handle。    this=interface--+
                        |   +------->ComObject
                  +<----+   |
                  |         |
                  +-------->+
      

  16.   

    Com的数据是应该全部被封装起来的吧?
      

  17.   

    我觉得this指针是指向数据成员的,接口指针也是实例对象的数据成员,vtlb的地址是一样的,但指向它的接口的地址(接口指针)当然可以不一样,即使是在同一个进程中,同一个接口指针在不同套间中的值也是不一样的。
      

  18.   

    to 毛刚:
    -------------------------------------------------------------------------------
    这么说,N 个接口指针也是this 的话,N 个接口指针 的值也是相等的,但事实上同一个COM对象不同的接口指针的值是不一样的,所以说接口指针并不是this指针。
    -------------------------------------------------------------------------------你说的这个问题我也同样觉得,这个this指针不应该是接口指针,它应该是对象的所有数据地址的总入口,应该是由操作系统的组件服务程序维护的,调用queryinterface时,用户给入需要的接口名,然后this指针会自动的被传入。
      

  19.   

    先说明何谓this指针:
    class CA
    {
        long a;
        void A( long e );
        void B( long e );
    };
    上面的类定义实际上如下:
    struct s_CA
    {
        long a;
    };
    void CA_A( s_CA *this, long e );
    void CA_B( s_CA *this, long e );因此:
    CA a;       // 此时实际为: s_CA a; CA_CA( &a );  // 调用构造函数
    a.A( 34 );  // 此时实际如下:CA_A( &a, 34 );因此所谓的this指针就是struct s_CA的一个指针,而所谓的类实例其实就是一个结构的实例。而当出现虚函数时,假设如下:
    接口IA为:                            接口IB为:
    struct IA                             struct IB
    {                                     {
        void A( long e ) = 0;                 void B( long e ) = 0;
    };                                    };
    而CA派生自IA和IB,即实现IA和IB(用ATL的方式),此时s_CA变成如下:
    struct s_CA
    {
        void *pvt_A;  // 由于IA所引入的虚函数地址指针,也就是楼主所谓的一份函数拷贝
        void *pvt_B;  // 由于IB所引入的虚函数地址指针,也就是楼主所谓的一份函数拷贝
        long a;
    };此时:
    CA a;
    IA *pA = static_cast< IA* >( &a );  // 此时pA == &a
    IB *pB = static_cast< IB* >( &a );  // 此时pB == &a + 4,跳过pvt_A,
                                        // 由static_cast这个指令进行转换的
    pA->A( 34 );  // 此时实际为( *pA->pvt_A[0] )( pA, 34 );
    pB->B( 34 );  // 此时实际为( *pB->pvt_B[0] )( pB, 34 );
    而pA->pvt_A[0]的函数原型为void CA_A( IA *this, long e );
    而pB->pvt_B[0]的函数原形为void CA_B( IB *this, long e );因此就有函数CA_A和CA_B,而CA_A的this指针是IA*,CA_B的this指针是IB*,即调用接口函数时传递的this指针就是那个接口的指针,但是数据是怎么传递的呢?即编译器如何知道IA*加上8个字节后就是成员变量a的值?很简单,因为CA_A和CA_B是类CA实现的,因此编译器在编译CA_A时知道此时传进来的this+8就是成员变量a的地址,在CA_B时知道此时传进来的this+4就是成员变量a的地址,因为编译器在编译这两个函数时是知道类CA的定义的,即编译器知道如下:
    class CA : public IA, public IB
    {
        long a;
        void A( long e );
        void B( long e );
    };
    所以编译器知道传进来的this到底是个什么类的实例,因而可以表现出通过传递虚函数列表的指针就达到了传递数据成员的现象。
      

  20.   

    楼上讲得好长。
    我先前说的有错误,我更正一下:
    this指针是指向当前类实例的指针,类实例是一群数据成员的集合,其中包括vtbl指针,通过多继承方法得到的类的类实例,包含它所继承的所有接口的vtbl的指针,我们可以使用static_case<IXXX*>把this指针强制转换为指向对应IXXX接口的vtbl的指针的指针(因为vtbl指针是类实例的数据成员,编译器只需调整this指针加上一个适当的偏移量即可指向它)。很显然我们通过this指针强制转换,从而得到了指向vtbl的指针的指针,也就得到了所谓的借口指针。
    另外,类的各个实例将共享相同的vtbl(但各自拥有指向它的指针)和函数实现。
      

  21.   

    COM只是一种调用约定,对象不一定是在本进程内,甚至有可能在其它计算机上,其它计算机可以运行不同的操作系统
      

  22.   

    综合各位的解释,我这样理解:一个对象被创建以后,产生了一个指向该对象入口的指针(就按c++的名称叫做this指针好了),而我们获得的总是一个接口指针,这个接口指针通过
    static_cast<interface*>this 强制类型转换来得到,它应该是一个指向该接口虚函数表的指针。如果这样,对于同一个对象,不同的接口指针当然是不一样的,但是对于同一个com组件的不同对象,如果它们查询同样的接口,那么应该要获得同样的指针了?
      

  23.   

    To:GnoDreamNa(only you)
    我认为你走入误区了,在考虑this指针的时候,不应该把它与com联系起来讲,原因有三:
    一、this是C++语言的中概念
    二、COM规范中并无this的说法
    三、在查询COM对象时,只能获知COM对象的接口指针
      

  24.   

    补充一点,C++的this问题,建议看一下《C++组件对象模型》,可能有答案
      

  25.   

    lop的解释非常详细,我想基本上都通了,不过刚才还有一个错误,得到的接口指针应该不是指向虚函数表,而是指向对象中一个指向虚函数表的指针。这样,不管对于同一个对象的不同接口,还是同一个接口的不同对象,指针都不一样了。