刚刚开始学com, 发现很多c的基础知识都不懂. 
IX* pIX = NULL;
HRESULT hr = pI->QueryInterface(IID_IX, (void**)&pIX)
...
...
HRESULT __stcall CA::QueryInterface(const IID& iid, void** ppv)
{
   if(iid == IID_IUnknown)
   {
      *ppv = static_cast<IX*>(this)
   }
   ...
}其中 (void**)&pIX 怎么解释, 我怎么也看不懂. 还有 *ppv 我也看不懂

解决方案 »

  1.   

    void** 几时指向void*的指针阿
      

  2.   

    你还是先把C++基础打好了再学COM吧,偶觉得。
      

  3.   

    你还是先把C++基础打好了再学COM吧,偶觉得。
      

  4.   

    QueryInterface的作用就是查询指定(第一个参数)的接口,并返回该接口的指针(第二个参数),既然是接口(本身是指针类型),参数中又只能通过指针返回值,那么该参数据的形式就只能是指向指针的指针了,void**的作用就是可以传递各种类型的指针
    pI->QueryInterface(IID_IX, (void**)&pIX)
    IID_IX是你要查询的接口的GUID,pIX是接口,而&pIX是其地址
    在下面的代码中
    HRESULT __stcall CA::QueryInterface(const IID& iid, void** ppv)
    {
       if(iid == IID_IUnknown)
       {
          *ppv = static_cast<IX*>(this)
       }
       ...
    }*ppv = static_cast<IX*>(this)
    的*ppv就相当于pIX,上面一行的作用就是为pIX指定值。
    调用成功后,就可以通过pIX访问接口的方法。如pIX->...
      

  5.   

    谢谢FBStudio(飞鸟)和LeeZi的指教.void**的作用就是可以传递各种类型的指针, 那void* 不也是可以传递各种类型的指针么, 请解释一下.
      

  6.   

    反对 LeeZi(临渊羡鱼,不如退而结网)的意见
    楼主不应该补习C++,而应该补习C
    注意void *pv 和 void **ppv的区别
    一个是指针,一个是二级指针,是指向指针的指针
    &pv就是指针的地址,相当于ppv,
    (void**)&pv,只不过将指针的地址转化为二级指针
      

  7.   

    参数传递是以拷贝形式进行的。如:
    void swap(int a,int b){
     int tem=a;
     a=b;
     b=tem;
    }///调用int a=10,b=20;
    swap(a,b);
    cout<<a<<end;cout<<b<<end;
    ///////////////////
    a和b的值不会被交换,交换的只是他们的拷贝。
    可以swap(int *a,int *b)来实现a,b值的交换。
    同样道理,要想从参数中返回地址,就要一指针的指针的形式获得。这也是
    QueryInterface(const IID& iid, void** ppv)
    第二个参数是void **的原因。
      

  8.   

    同意: fantong(IT民工 饭桶)void类型是可以避免编译器进行类型检测,而调用方与被调用方必须在类型上达成一致
      

  9.   

    void**的作用就是可以传递各种类型的指针, 那void* 不也是可以传递各种类型的指针么, 请解释一下.
    注意,传void*只能改变指针指向的指,传void**才能改变void*这个指针!呵呵,多多学习:)
      

  10.   

    如果你在函数重要改变一个变量的值,那么应该在参数中传变量的指针,如果你要改变的是一个指针的指向呢?自然就应该传这个指针的指针啦这就是(void**)&pIX的作用
      

  11.   

    实际上QueryInterface的第二个参数是微软为了在视觉上避免用户调用时
    与第一个参数类型不对应,也就是说如果第二个参数的指针类型不
    为第一个参数的接口指针型类就有可能造成查询错误(因为c++编译器不会报错)。
    (void**)这种类型转换本身就是类型不安全的。
      

  12.   

    void * 它不区分类型用来传递地址,它应该是默认只能指向基本类型int, float, bool。而指针等其他数据类型属于复合类型。因此为了表示指向一个(复合的)指针,
    就不能用void * ,而是用指向指针的指针。首先应在情感上认同它。至于类型转换是否安全,可以参考bjarne的D&E里面说"即或在窄转换,因为有时真的没有丢失数据,有时的数据截断是用户需要的"。在《程序设计实践》里面也可常见这种做法,它给了这样的表达方式"...转换为适当类型..."。搂主如此认真,我觉得很好,而且我觉得你的水平还要在我之上:)
    应该多看书,开卷有益。祝进步!
      

  13.   

    呵呵,C语言的基础不扎实啊,回头好好补一补哦
    &pIX 是一个接口指针的地址
    (void**)将这个指向指针的指针转换为指向 void 指针的指针
    呵呵,是不是还是很晕
    如果要改变一个指针的值,那么传送的要么是指针的引用,要么就是指针的地址(指针的指针)
      

  14.   

    我想楼上的很多人都说得很好了,但是我没去挨个的看。我觉得这与C++无关,属于C的内容要想在参数上返回值,你可以看以下谭浩强的C程序设计,其实很简单,只需要把这个数据的指针给它就OK了。
    例如:
    void getValue(int *pVal)
    {
       *pVal = 20;
    }
    int main()
    {
       int iValue;
       getValue(&iValue);
       cout<<iValue<<endl;
    }
    这样你的屏幕上就会打印出20的字样。上例中是要得到INT型的值,就把参数定义成int型指针。
    而COM要得到的是接口的指针,所以就需要把接口指针的指针给它就OK了。
    如:
    HRESULT QueryInterface(IID &iid,Interface **ppInterface)
    {
      if(....)
       *ppInterface = static_cast<...>(this);
    }
    int main()
    {
       Interface *pInterface;
       pObj->QueryInterface(iid,&pInterface);  //pObj是同一对象的另外的一个接口
    }
    而COM中QueryInterface(IID &iid,Interface **ppInterface)中要查询的接口不可能只一个Interface类型这么简单,多数有实际意义的COM类会支持很多接口。这就需要参数返回的是多种类型,所以COM中就采用了如下的方法
    HRESULT QueryInterface(IID &iid,void **ppInterface)
    {
       if(...)
         *ppInterface = static_cast<...>(this);
    }int main()
    {
       Interface *pInterface;
       pObj->QueryInterface(iid,(void **)&pInterface);
    }
      

  15.   

    IX* pIX = NULL;
    HRESULT hr = pI->QueryInterface(IID_IX, (void**)&pIX);IX* pIX = NULL;
    HRESULT hr = pI->QueryInterface(IID_IX, (void**)&pIX)
    pIX即然要的是接口指针我看Void*就行了。再加一级指针无非就是要
    编译器出现类型转型警告。《com本质论》上有说的。