Я читаю образец COM в 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 **). Что делает (недействительным **)&pControl хотите вернуть?
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 установлен в НОЛЬ.
Итак, в вашем конкретном случае, после успешного возвращения, 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*').
Других решений пока нет …