COM組件開發實踐(五)---From C++ to COM :Part 2 __C++

來源:互聯網
上載者:User
COM組件開發實踐(五)---From C++ to COM :Part 2

一,使用抽象基類重用C++對象

在上一篇文章《COM組件開發實踐(四)---From C++ to COM :Part 1》中,我們已經將要複用的C++對象封裝到DLL中了,對象的聲明和實現已經實現了剝離,但還有問題:對象的私人成員(如我們樣本中CDB類的陣列變數m_arrTables)還是被客戶看得一清二楚,即使客戶沒辦法去訪問它們;若對象改變了它的資料成員的大小,則所有的客戶程式必須重新編譯。

而實際上,客戶需要的僅僅是對象的成員函數的地址,因此使用抽象基類可以很好地滿足以上需求,客戶就不會包含對象的私人資料成員,就算對象改變了資料成員的大小,客戶程式也不用重新編譯。

1.      修改介面檔案

首先將介面都改成抽象基類,這是客戶程式唯一所需要的代碼。具體包括下面幾步:1)將CDB和CDBSrvFactory的函數都改成純虛函數。2)刪除資料成員。3)刪除所有成員函數的引出標誌。4)將CDB改成IDB(表示DB的介面),CDBSrvFactory改成IDBSrvFactory(表示DB類工廠的介面) typedef  long  HRESULT;
#define  DEF_EXPORT __declspec(dllexport)
class  IDB 
{
     //  Interfaces
public :
     //  Interface for data access
     virtual  HRESULT Read( short  nTable,  short  nRow, LPWSTR lpszData)  = 0 ;
     virtual  HRESULT Write( short  nTable,  short  nRow, LPCWSTR lpszData)  = 0 ;
     //  Interface for database management
     virtual  HRESULT Create( short   & nTable, LPCWSTR lpszName)  = 0 ;
     virtual  HRESULT Delete( short  nTable)  = 0 ;
     //  Interfase para obtenber informacion sobre la base de datos
     virtual  HRESULT GetNumTables( short   & nNumTables)  = 0 ;
     virtual  HRESULT GetTableName( short  nTable, LPWSTR lpszName)  = 0 ;
     virtual  HRESULT GetNumRows( short  nTable,  short   & nRows)  = 0 ;
     virtual  ULONG Release()  = 0 ;
};
class  IDBSrvFactory 
{
     //  Interface
public :
     virtual  HRESULT CreateDB(IDB **  ppObject)  = 0 ;
     virtual  ULONG   Release()  = 0 ;
};

HRESULT DEF_EXPORT DllGetClassFactoryObject(IDBSrvFactory  **  ppObject);

2.修改對象程式

在DLL項目中,我們實現為這個抽象介面聲明並實現具體的子類,讓CDB從IDB派生,CDBSrvFactory從IDBSrvFactory派生,並且把類工廠CDBSrvFactory的CreateDB方法的參數由CDB**改成IDB**。 #include  " ../interface/dbsrv.h "
typedef  long  HRESULT;
class  CDB :  public  IDB
{
     //  Interfaces
public :
     //  Interface for data access
    HRESULT Read( short  nTable,  short  nRow, LPWSTR lpszData);
    HRESULT Write( short  nTable,  short  nRow, LPCWSTR lpszData);
     //  Interface for database management
    HRESULT Create( short   & nTable, LPCWSTR lpszName);
    HRESULT Delete( short  nTable);
     //  Interfase para obtenber informacion sobre la base de datos
    HRESULT GetNumTables( short   & nNumTables);
    HRESULT GetTableName( short  nTable, LPWSTR lpszName);
    HRESULT GetNumRows( short  nTable,  short   & nRows);
    ULONG Release();  // CPPTOCOM: need to free an object in the DLL, since it was allocated here
     //  Implementation
private :
    CPtrArray m_arrTables;       //  Array of pointers to CStringArray (the "database")
    CStringArray m_arrNames;  //  Array of table names
public :
     ~ CDB();
};
class  CDBSrvFactory :  public  IDBSrvFactory 
{
     //  Interface
public :
    HRESULT CreateDB(IDB **  ppObject);
    ULONG   Release();
};

     這兩個具體子類的實現代碼在此就省略不表了,參考上篇文章。

3.修改客戶程式

      最後根據上面的修改,對客戶程式也做相應修改:1)將CDBDoc類的資料成員類型由CDB*改成IDB*。 IDB  * m_pDB;  //  pointer to database object

  2)CDBDoc::OnNewDocument函數中,將CDBSrvFactory*改成IDBSrvFactory* BOOL CDBDoc::OnNewDocument()
{

     // 建立資料庫物件
     // m_pDB=new CDB;
    IDBSrvFactory  * pDBFactory = NULL;
    DllGetClassFactoryObject( & pDBFactory); 
    pDBFactory -> CreateDB( & m_pDB);
    pDBFactory -> Release();  //  do not need the factory anymore
     //  初始化資料成員變數

     return  TRUE;
}

     OK,最後重新編譯DLL即可。可以看出,通過使用虛函數和抽象基類,這才算真正實現了面向介面編程。

 

     二,初步逼近COM--使用COM庫載入C++對象

      上面的代碼中聲明了DLL的一個進入點DllGetClassFactoryObject,而客戶程式就是通過調用這個函數,從而擷取到相應的類工廠對象,再使用類工廠對象建立真正的對象的。我們這一步要嘗試讓客戶程式不去直接調用對象的入口函數,而是讓COM庫為我們服務,並且要讓對象使用標準的入口函數。

1,修改介面定義檔案

      首先在介面定義檔案中增加類ID和介面ID的聲明,這兩個ID在對象程式和客戶程式中都會有定義,在這裡只是對這兩個外部變數進行說明。然後將引出函數DllGetClassFactoryObject刪除,因為接下來我們將會使用標準入口函數DllGetObject,因此不需要再自己定義入口函數了。2,修改對象程式 typedef  long  HRESULT;
#define  DEF_EXPORT __declspec(dllexport)
//  {30DF3430-0266-11cf-BAA6-00AA003E0EED}
extern   const  GUID CLSID_DBSAMPLE;
// { 0x30df3430, 0x266, 0x11cf, { 0xba, 0xa6, 0x0, 0xaa, 0x0, 0x3e, 0xe, 0xed } };
//  {30DF3431-0266-11cf-BAA6-00AA003E0EED}
extern   const  GUID IID_IDBSrvFactory;
// { 0x30df3431, 0x266, 0x11cf, { 0xba, 0xa6, 0x0, 0xaa, 0x0, 0x3e, 0xe, 0xed } };
class  IDB 
{
   //  Interfaces
   public :
           //  Interface for data access
         virtual  HRESULT Read( short  nTable,  short  nRow, LPWSTR lpszData)  = 0 ;
         virtual  HRESULT Write( short  nTable,  short  nRow, LPCWSTR lpszData)  = 0 ;
         //  Interface for database management
         virtual  HRESULT Create( short   & nTable, LPCWSTR lpszName)  = 0 ;
         virtual  HRESULT Delete( short  nTable)  = 0 ;
         //  Interfase para obtenber informacion sobre la base de datos
         virtual  HRESULT GetNumTables( short   & nNumTables)  = 0 ;
         virtual  HRESULT GetTableName( short  nTable, LPWSTR lpszName)  = 0 ;
         virtual  HRESULT GetNumRows( short  nTable,  short   & nRows)  = 0 ;
         virtual

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.