爲什麼COM裏的QueryInterface第二個參數需要使用雙重指針?

轉載自:http://www.cnblogs.com/perhaps/archive/2004/09/08/41143.html

昨天向COM的世界邁出了第一步,雖然沒有想象中那樣舉步維艱,卻也走得不輕鬆。在初步瞭解DirectX的基礎——COM之後,再次將注意力轉到DirectX上來。正如一篇介紹COM的文章所說的,使用COM遠比了解COM要簡單得多。確實,在DirectX中使用COM都是那樣的自然,跟一般函數的調用並無二致。但是,使用起來很自然還是沒有阻止自己腦袋瓜中不斷涌出的問號。大家看以下代碼:

LPDIRECTDRAW lpdd = NULL;
if( FAILED(lpdd->QueryInterface(IID_IDirectDraw7, (LPVOID *&
lpdd)))
    
{
          
//error handle and return

    }

代碼很簡單,就是調用了QueryInterface方法去獲得DirectDraw7的接口指針。然而我第一眼看過去的時候,總是覺得有點彆扭。大家再看一下,我昨天實現第一個COM對象的時候override的QueryInterface方法:

HRESULT __stdcall ComObject::QueryInterface(const IID &iid, void ** iface)
{
    
if(iid ==
 IID_IX)
       
*iface = (InterfaceX*this
;
    
else
 
        
if (iid ==
 IID_IY)
            
*iface = (InterfaceY*this
;
    
else

        
*iface = 0;
        
return
 E_NOINTERFACE;
        ((IUnknown
*) (*iface))->
AddRef();
    
return
 (S_OK);
}


        我覺得彆扭是因爲第二個參數少了個dereference操作符,儘管LPVOID就是void *,但是通過使用typedef關鍵字
將其定義爲LPVOID,確實讓代碼可讀性更高了。這是我想到第一個問題;
        接着就是一個感覺很低級的問題了:QueryInterface爲什麼要使用指針的指針作爲參數呢?直接用指針不行嗎?
如果僅僅是爲了在函數體中能夠改變參數,使用指針就足夠了。那是因爲什麼呢?我們從如下形式的QueryInterface方法來看:

HRESULT QueryInterface( REFIID iid, void ** ppvObject);
HRESULT QueryInterface( REFIID riid,LPVOID 
*
ppvObj);

        第一,ppvObject這個參數的含義是接口指針的地址(Address of a pointer to fill with the interface pointer)。從這個角度而言,第二種函數形式就更爲容易理解了,由於"*"爲解引用操作符,作用於ppvObject,得到的類型正好就是一個接口指針了(與LPVOID相對應);
        第二,QueryInterface如果執行成功,就會將相應的接口指針賦給參數*ppvObject,如果僅僅是傳遞接口指針本
身,而非接口指針的地址,就無法在函數體中對其進行賦值了。大家看以下代碼:

class X
{
public
:
 
virtual void
 sayHi(); 
}
;

class Y:public
 X
{
public
:
 
void
 sayHi();
}
;

                                                                                    (Test.hpp)

#include <iostream>
#include 
"Test.hpp"

using namespace std;

void
 X::sayHi()
{
 cout 
<< "Hi, My name is X." <<
 endl;
}


void Y::sayHi()
{
 cout 
<< "Hi, My name is Y." <<
 endl;
}


void change(X *x)
{
  x 
= new
 Y;
}


void main()
{
 X
* a = new
 X;
 a
->
sayHi();
 change(a);
 a
->
sayHi();
}


        大家會覺得輸出是什麼呢?我們所期待的Y給大家的問候語並沒有出現,就剩下X在唱獨角戲。不管如何折騰,Y就是不會出現。如果使用了指針的指針,我們就可以得到體現多態的結果了。
        PS:其實這是一個很簡單的問題,但是通過摸索讓自己對雙重指針有了進一步的認識,以前就知道雙重指針的定義就是指針的指針,至於它爲什麼會存在,一點想法都沒有。在瞎胡鬧的過程中,同時還強化了一個概念,就是運算符的優先級,類型轉化的優先級要比"->"和"."要低。
        我還是C++方面的菜鳥,各位高手看了,笑笑就好了,別笑太大聲哦。 :)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章