在类厂创建了一个实例对象后,当然也就有一个指针指向了该对象,接下来我不调用QueryInterface(),然后我就用这个指针来调用接口中的函数,这样行吗?
我一直在QueryInterface()这里弄不明白:感觉类厂创建了一个对象,那么对象的指针就可以直接调用接口中的函数,干吗还有调用QueryInterface()来实现接口,有点迷糊?请大家给予解释,谢谢!

解决方案 »

  1.   

    暴风影音调用控件,就是直接获得接口函数的地址的
    这是一个大工程,需要精通com
      

  2.   

    下面是类厂创建一个对象,创建后调用QueryInterface();发现QueryInterface()中的语句*ppv = this就是将对象的指针赋值给*ppv;所以我理解调用QueryInterface()好像是多此一举!static HRESULT STDMETHODCALLTYPE classCreateInstance(IClassFactory *this, IUnknown *punkOuter, REFIID vTableGuid, void **objHandle)
    {
    HRESULT hr;
    register IExample *thisobj;
    *objHandle = 0;
    if (punkOuter)
    hr = CLASS_E_NOAGGREGATION;
    else
    {
    if (!(thisobj = (IExample *)GlobalAlloc(GMEM_FIXED, sizeof(MyRealIExample))))
    hr = E_OUTOFMEMORY;
    else
    {
    thisobj->lpVtbl = (IExampleVtbl *)&IExample_Vtbl;
    ((MyRealIExample *)thisobj)->count = 1;
    ((MyRealIExample *)thisobj)->buffer[0] = 0;
    hr = IExample_Vtbl.QueryInterface(thisobj, vTableGuid, objHandle);
    IExample_Vtbl.Release(thisobj);
    if (!hr) InterlockedIncrement(&OutstandingObjects);
    }
    }
    return(hr);
    }
    static HRESULT STDMETHODCALLTYPE QueryInterface(IExample *this, REFIID vTableGuid, void **ppv)
    {
     
    if (!IsEqualIID(vTableGuid, &IID_IUnknown) && !IsEqualIID(vTableGuid, &IID_IExample))
    {
          *ppv = 0;
          return(E_NOINTERFACE);
    }
    *ppv = this;
    this->lpVtbl->AddRef(this);
    return(NOERROR);
    }
      

  3.   

    一个对象可以有多个接口,QueryInterface的具体实现可以很不一样,比如把内部的对象的接口直接暴露。所以你说的"对象指针"并不能代表接口地址。实际上com里没有对象指针的,访问对象都通过接口。
    为了从一个接口找到其他的接口,就要QueryInterface。
      

  4.   

    已经有一个对象的IExample接口(Create时或QueryInterface或其他途径获得的,这个可不是“对象指针”,是接口指针),要查询vTableGuid表示的其他接口
    static HRESULT STDMETHODCALLTYPE QueryInterface(IExample *this, REFIID vTableGuid, void **ppv)
    {
        if (!IsEqualIID(vTableGuid, &IID_IUnknown) && !IsEqualIID(vTableGuid, &IID_IExample))
        {
    //该对象只支持IUnknown和IExample接口,如果询问其他接口,就返回NULL表示不支持。
          *ppv = 0;
          return(E_NOINTERFACE);
        }
        *ppv = this;//这个this不是c++的this,这是C代码,this是传进来的参数。
        this->lpVtbl->AddRef(this);//增加对象的引用计数
        return(NOERROR);
      

  5.   

    这里的参数this不是指向一个实例化IExample的指针吗?
      

  6.   

    QueryInterface()是用来获取接口的,不是用来实现接口的,如果你用CreateXX创建的接口里已经实现了所有函数而所继承的接口里没有相同的函数的话,那就可以不用QueryInterface()来得到其它接口了
      

  7.   

    在上面的代码中classCreateInstance创建了一个对象实例(就是thisobj指针指向了这个实例),然后又将thisobj 作为参数传递给QueryInterface()来实现接口,在QueryInterface()中又将this(thisobj)赋值给*ppv;所以我就感觉到这里QueryInterface()好像是多次一举;
      

  8.   

    对这个对象来说,QueryInterface意义不大,因为只有一个IExample接口,创建时获得就行了。但很多com对象都有很多接口的。
    创建函数这么写也是有道理的。比如对象增加接口了,那么"多此一举"后,就只需要修改QueryInterface就行了,而创建函数不用改,用户用新的REFIID就可以在创建时获得新的接口。
      

  9.   

    只有一个接口时,还必须要调用QueryInterface(),负责的话,该COM组件的接口函数不能被调用.
    刚才测试:注释掉QueryInterface()方法的调用!
      

  10.   

    hr = IExample_Vtbl.QueryInterface(thisobj, vTableGuid, objHandle);
    没有这一句,objHandle没有赋值。
      

  11.   

    删掉:
    hr = IExample_Vtbl.QueryInterface(thisobj, vTableGuid, objHandle);
    添加:
    *objHandle=thisobj;
    还是不行
      

  12.   

    掉用出现:
    "0x00310032"指令引用的"0x00310032"内存,该内存不能为"written"
      

  13.   

    调用出现:
    "0x00310032"指令引用的"0x00310032"内存,该内存不能为"written"
    这样的话,还必须要调用QueryInterface()
      

  14.   

    你没有调用QueryInterface的话,引用计数没有++.
    IExample_Vtbl.Release(thisobj);
    这一句之后,对象释放掉了。
      

  15.   

    QueryInterface的意义远不止指针转换这么简单
    ...所有接口都是IUnknown,但IUnknown什么都不是(这也是这个名称的意义)。换句话说,任何接口都可以直接转换成IUnknown并调用IUnknown的方法,但给你一个IUnknown接口,你说它是IA还是IB?QueryInterface的意义就来了,它不关心实现这个接口的组件是如何实现的,也不关心组件实现了几个接口,更不关心接口是被组件直接继承的还是包容的还是聚合的,所有这些细节都是组件的内政,不容外部干涉。楼主的假设并非不对,但只是一种组件具体实现方式而已,即无通用性也没代表性。...接口是语言无关的,你怎么能把一个接口强制转换成一个C++指针呢,其它语言创建的接口怎么转换?...在多线程或多进程环境下,组件接口都是要列集散列的,即使某个接口满足楼主假设的所有条件(C++类实现的单接口),你也不能把接口指针强制转换成C++指针,因为代理指针只代理接口,不代理组件,强制转换的后果是不可预料的。QI的作用还有很多,这几条理由够不够用?