简体   繁体   中英

Void pointer pointer (void **)

I am reading a COM sample at http://msdn.microsoft.com/en-us/library/windows/desktop/dd389098(v=vs.85).aspx

I really cannot comprehend (void **) in

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

So I have tried some values returned by different types of pointers by the class

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 << ")";
}

and printing out

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

(void*) really has no difference with (void **). What does (void **)&pControl want to return?

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

What does (void **)&pControl want to return?

QueryInterface() is one of the three methods of IUnknown , which is the base root interface of all COM interfaces.

The MSDN documentation for IUnknown::QueryInterface() clearly states that:

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

ppvObject [out] The address of a pointer variable that receives the interface pointer requested in the riid parameter. Upon successful return, *ppvObject contains the requested interface pointer to the object. If the object does not support the interface, *ppvObject is set to NULL .

So, in your particular case, upon successful return, pControl will contain the requested pointer to the IMediaControl interface, as specified in your function call via the first argument IID_IMediaControl .


Now, let's try to better understand why the double pointer indirection: void** .

void* means "pointer to anything" .

So, one might think: "Why isn't the second parameter of QueryInterface() just a void* ?"

The problem is that this parameter is an output parameter. This means that QueryInterface() will write something into that parameter, for the caller to use it.

And, in C (and COM has several C-isms), when you have an output parameter, you must use a pointer ( * ).
( Note In C++ you can also use a reference & .)

So, in this case we have the first level of indirection of void* that means "pointer to anything" .
And the second level of indirection (the other * ), that means: "This is an output parameter" .

You can think of it also in this way:

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*').

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM