无效指针指针(无效**)

Void pointer pointer (void **)

本文关键字:无效 指针      更新时间:2023-10-16

我正在http://msdn.microsoft.com/en-us/library/windows/desktop/dd389098(v=vs.85).aspx

我真的无法理解中的(无效**)

hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);

因此,我尝试了类不同类型指针返回的一些值

class Point{
private:
    int x, y;
public:
    Point(int inputX, int inputY){x = inputX, y = inputY;}
    int getX(){return x;}
    int getY(){return y;}
    friend ostream& operator << (ostream &out, Point &cPoint);
    Point operator-(){
        return Point(-x, -y);
    }
};
ostream& operator << (ostream &out, Point &cPoint){
    return out<< "(" << cPoint.x << ", " << cPoint.y << ")";
}

并打印出

Point *p = new Point(1,2);
cout << p << endl << &p << endl << endl
<< *&p << endl<< **&p << endl<<endl 
<< (void *) &p << endl << (void **) &p ;

(void*)实际上与(void**)没有区别。什么是(void**)&pControl要返回吗?

hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);

(void **)&pControl想要返回什么?

QueryInterface()IUnknown的三种方法之一,是所有COM接口的基本根接口。

IUnknown::QueryInterface()的MSDN文档明确指出:

HRESULT QueryInterface(
  [in]   REFIID riid,
  [out]  void **ppvObject
);

ppvObject[out]接收riid参数中请求的接口指针的指针变量的地址。成功返回后,*ppvObject包含请求的指向对象如果对象不支持接口,*ppvObject将设置为NULL

因此,在您的特定情况下,成功返回后,pControl将包含指向IMediaControl接口的请求指针,如函数调用中通过第一个参数IID_IMediaControl指定的那样。


现在,让我们试着更好地理解为什么使用双指针间接寻址:void**

void*的意思是"指向任何东西的指针"。

因此,人们可能会想:"为什么QueryInterface()的第二个参数不只是void*?"

问题是此参数是输出参数。这意味着QueryInterface()将在该参数中写入内容,供调用方使用。

而且,在C中(COM有几个C语言),当您有一个输出参数时,您必须使用指针*
(注意在C++中,您也可以使用参考&。)

因此,在这种情况下,我们有void*的第一级间接性,这意味着"指向任何东西的指针"
第二个间接级别(另一个*),意思是:"这是一个输出参数"

你也可以这样想:

typedef void* PointerToAnything;
HRESULT QueryInterface(..., /* [out] */ PointerToAnything* pSomeInterface);
// pSomeInterface is an output parameter.
//
// [out] --> use * (pointer), 
// so it's 'PointerToAnything*' (not just 'PointerToAnything'),
// so, with proper substitution, it's 'void**' (not just 'void*').