4

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

我真的无法理解 (void **) in

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 想要返回什么?

4

1 回答 1

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

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

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

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

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

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

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


现在,让我们尝试更好地理解为什么双指针间接:void**.

void*意思是“指向任何东西”

所以,有人可能会想:“为什么不QueryInterface()只是 a的第二个参数void*?”

问题是这个参数是一个输出参数。这意味着将QueryInterface()该参数中写入一些内容,供调用者使用。

而且,在 C 语言中(并且 COM 有几个 C-isms),当你有一个输出参数时,你必须使用一个指针( *)。
注意在 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*').
于 2014-04-15T18:57:34.407 回答