刚开始学com, 小弟请教各位, 在 pI->QueryInterface(IID_IX, (void**)&pIX)中, (void**)&pIX 怎么解释,

时间:2021-01-27 18:26:08
刚刚开始学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 我也看不懂

18 个解决方案

#1


高手都不在线么!

#2


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

#3


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

#4


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

#5


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->...

#6


谢谢FBStudio(飞鸟)和LeeZi的指教.

void**的作用就是可以传递各种类型的指针, 那void* 不也是可以传递各种类型的指针么, 请解释一下.

#7


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

#8


参数传递是以拷贝形式进行的。如:
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 **的原因。

#9


同意: fantong(IT民工 饭桶)

void类型是可以避免编译器进行类型检测,而调用方与被调用方必须在类型上达成一致

#10


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

#11


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

#12


大家都说的好啊

#13


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

#14


void * 它不区分类型用来传递地址,它应该是默认只能指向基本类型int, float, bool。而指针等其他数据类型属于复合类型。因此为了表示指向一个(复合的)指针,
就不能用void * ,而是用指向指针的指针。首先应在情感上认同它。

至于类型转换是否安全,可以参考bjarne的D&E里面说"即或在窄转换,因为有时真的没有丢失数据,有时的数据截断是用户需要的"。在《程序设计实践》里面也可常见这种做法,它给了这样的表达方式"...转换为适当类型..."。

搂主如此认真,我觉得很好,而且我觉得你的水平还要在我之上:)
应该多看书,开卷有益。祝进步!

#15


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

#16


我想楼上的很多人都说得很好了,但是我没去挨个的看。我觉得这与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);
}

#17


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本质论》上有说的。

#18


up

#1


高手都不在线么!

#2


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

#3


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

#4


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

#5


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->...

#6


谢谢FBStudio(飞鸟)和LeeZi的指教.

void**的作用就是可以传递各种类型的指针, 那void* 不也是可以传递各种类型的指针么, 请解释一下.

#7


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

#8


参数传递是以拷贝形式进行的。如:
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 **的原因。

#9


同意: fantong(IT民工 饭桶)

void类型是可以避免编译器进行类型检测,而调用方与被调用方必须在类型上达成一致

#10


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

#11


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

#12


大家都说的好啊

#13


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

#14


void * 它不区分类型用来传递地址,它应该是默认只能指向基本类型int, float, bool。而指针等其他数据类型属于复合类型。因此为了表示指向一个(复合的)指针,
就不能用void * ,而是用指向指针的指针。首先应在情感上认同它。

至于类型转换是否安全,可以参考bjarne的D&E里面说"即或在窄转换,因为有时真的没有丢失数据,有时的数据截断是用户需要的"。在《程序设计实践》里面也可常见这种做法,它给了这样的表达方式"...转换为适当类型..."。

搂主如此认真,我觉得很好,而且我觉得你的水平还要在我之上:)
应该多看书,开卷有益。祝进步!

#15


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

#16


我想楼上的很多人都说得很好了,但是我没去挨个的看。我觉得这与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);
}

#17


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本质论》上有说的。

#18


up