C O M 技術縱橫談 一(轉載)
一:概述
PC機自從誕生以來,硬件經歷了無數變化,CPU從最初的INTEL 8086到 現在PIII滿大街都是也只不過十幾年。微軟的WINDOWS操作系統從最初的 1.0版本到現在即將推出WIN2000,一直是桌面系統上裝機量最大的OS。 作爲軟件開發人員,使用着包括Visual Basic,Visual C++,Delphi包 括最新的Borland C++ builder等等在內的衆多開發環境爲WINDOWS開發 應用程序。應該說現在的開發條件和若干年以前比已經是大大的進步了。 如果你開發過16位的WINDOWS程序,你可能知道爲了讀取一個文件,我 們不得不使用一小段彙編來調用DOS例程,或者使用當時WINDOWS尚未公開 的函數:_lopen()。在win32環境下,你所要做的全部是調用 : :CreateFile()來獲得一個文件句柄,當然如果使用MFC或是OWL之類的 東西,你可以更簡單的做到。不過一般情況下,程序員仍然不得不從頭 開始寫編寫應用程序的每一行代碼。 但這種情況得到了改變:微軟提出了C O M(Component Object Model, 中文也可以譯作"組件對象模型")概念,並且在最新的WINDOWS95/98以 及WIN NT4中越來越廣泛的使用它:我們有理由相信在不久的將來,C O M 將成爲構建應用程序最普遍的方法,如果你對此技術有興趣,不妨參考本 文,希望從中你能學到想知道的知識。如果你已經是C O M老手,也歡迎 你批評指正
本文是針對C++程序員寫的。在介紹概念的時候,我儘量不把WIN32 API 的知識混合進來,以便你能夠更清晰的看到C O M的本質。所有的例子都 用Microsoft Visual C++5(SP3)編譯通過。 一般的講,一個應用程序總是由單個的二進制文件組成。在以前,如果 這個程序需要做一些改進,就要修改源代碼,然後編譯,聲稱新的文件, 然後取代原來的文件。現在,我們用一種全新的角度來看問題:把原先一 整個的EXE可執行文件,分割成功能不同,但相對獨立的幾個部分,把他 們拼裝起來,組成程序,組成軟件。在未來程序發佈以後,如果意識到需 要對他進行修改,只要替換有問題的或是需要升級的組建就可以了。甚至 可以做到再不影響程序正常運行的情況下替換其中的部件。如果你熟悉 WINDOWS編程,可能會想到:DLL似乎就是你所說的東西:可以動態下,動 態連接。事實上,COM正是充分利用了Win32 DLL的靈活性才得以真正在 Windows平臺上實現的。 這樣做有哪些優點呢?首先:用戶一般希望能夠定製所用的應用程序, 而組件技術從本質上講就是可被定製的,因而用戶可以用更能滿足他們需 要的某個組件來替換原來的那個。其次,由於組件是相對應用程序獨立的 部件,我們可以在不同的程序中使用同一個組件而不會產生任何問題,軟 件的可重用性將大大的得到增強。第三,隨着網絡帶寬及其重要性的提高, 分佈式網絡應用程序毫無疑問的成爲軟件市場上越來越重要的買點。組件 價構可以使得開發這類應用程序的過程得以簡化。 那麼,COM到底是什麼呢?它是一個說明如何建立可動態互變組件的規範。 他定義了一些爲保證能互操作,客戶(一個術語,指需要某種組件的程序) 組件必須遵循的標準,COM規範就是一套爲組件架構設置標準的文檔形 式的規範。COM的發佈形式是:以win32動態鏈接庫(DLL)或者可執行文件 (EXE)的形式發佈的可執行代碼組成。 COM組件是動態連接的,而且COM組件是完全與語言無關的。同時,COM組 件可以以二進制的形式發佈。COM組件還可以在不妨礙老客戶的情況下被升 級成新的版本。 你現在可以認爲,COM所能提供的服務有些類似C++中的類。不過類是基 於源代碼的,COM則不是。不過這裏要澄清一些關於COM的錯誤觀點:首先, COM不是一種計算機語言。把COM同某種計算機語言(如C++, VB)相比較是 沒有意義的。其次,也不要把DLL和COM做比較,因爲COM技術正是利用了 DLL的動態鏈接能力才得以實現的,而現在一般觀點則認爲,利用DLL動態 鏈接能力最佳的方法是COM。
當然,COM也不是win32 API那樣的一個函數集:它並沒有支持或者提供類 似MoveWindow這樣的函數來對系統進行特定的操作。COM也並不是類似於MFC 那樣的C++類庫。COM給開發人員提供的是一種開發與語言無關的組件庫的 方法,但COM本身並沒有提供任何實現。在一定程度上可以認爲COM是系統 無關的,software AG組織正在開發一系列COM支持系統,有望在不久的將 來,包括從Mac OS,VMS,SCO UNIX到LINUX的操作系統上都將得以實現COM。 COM的確有一些具體的實現。COM本身要實現一個稱爲COM庫(COM library) 的API,它提供諸如客戶對組件的查詢,以及組件的註冊/反註冊等一系列 服務,一般來說,COM庫由操作系統加以實現,程序員不必關心其實現的細 節。 總體來看,COM提供了編寫組件的一個標準方法。遵循COM標準的組件可 以被組合起來以形成應用程序。至於這些組件是誰編寫的,是如何實現的 並不重要。組件和客戶之間通過"接口"來發生聯繫。
二:什麼是接口
前面已經提到過,COM組件與客戶大家打交道的唯一辦法是通過接口。在
C++的實現中,我們一般用抽象基類來定義接口,然後利用C++類的多重繼
承實現該組件。下面給出一個簡單的示意:
//////////////// // iface.h ////////////////
#ifndef IFACE_H #define IFACE_H 1
#define interface class
interface IA { public: virtual func1() = 0; virtual func2() = 0; };
interface IB { public: virtual func3() = 0; virtual func4() = 0; };
#endif //////--iface.h end--//////
//////////////// // test.c ////////////////
#include "iface.h"
class Ca : public IA, IB { public: Ca(int i) : m_Count(i) {} virtual func1() { cout << "IA::func1 is " << m_Count * 1 << endl; } virtual func2() { cout << "IA::func2 is " << m_Count * 2 << endl; } virtual func3() { cout << "IB::func3 is " << m_Count * 3 << endl; } virtual func4() { cout << "IB::func4 is " << m_Count * 4 << endl; } int m_Count; };
main() { IA* pIa; IB* pIb; Ca* pCa = new Ca(2); pIa = pCa; pIa -> func1(); pIa -> func2(); pIb -> func3(); pIb -> func4(); delete pCa; } //////--test.c end--//////
上例中,定義了IA,IB兩個接口,你可以注意到他們所有的成員函數都
被聲明爲virtual,並且在函數末尾用 = 0 做了結束。類似這樣的函數
我們在C++中稱之爲純虛函數,如果整個的類都由純虛函數組成,那麼
這個類就叫做抽象基類。抽象基類本身由於沒有實體函數與變量,所以
並不分配內存。一般它的用途是爲派生類指定內存結構。打個比方來說,
就好像把房子分割成很多小間,規定以後哪些小間應該放什麼(函數的
實體)但具體的東西則要等派生類來填放。
這裏有一個概念需要說明一下:組件並不是類,上面我們用一個類就實
現了兩組接口,同樣我們也可以用它來實現更多接口。組件本身其實只
是一個接口集及其實現的集合。一個組件可能包含了多個接口,每一個
接口都有各自的實現。
|