程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> COM原理及應用----COM對象和接口

COM原理及應用----COM對象和接口

編輯:關於C++

1、COM對象的理解

COM對象類似於C++語言中類的概念,類的每個實例代表一個COM對象,它也包括屬性(即狀態)和方法(即操作),狀態反映對象的存在,方法就是接口。

2、COM對象的標識-CLSID

GUID是一個128位的隨機數,重復概率極低。它的值來源於兩部分:空間值(網卡地址或隨機數)和時間值。

獲得GUID值可以使用VC++提供的工具:GUIDGen.exe 和 UUIDGen.exe。或者使用COM庫的API函數CoCreatGuid()。

3、COM對象與C++對象的比較

COM對象將數據完全封裝在對象的內部。C++對象的封裝是在語義上的封裝,通過不同的數據類型實現數據的封裝。

COM對象的可重用性通過包容和聚合實現。C++對象的可重用性通過類的繼承來實現。

COM對象的多態性通過其接口體現,C++對象的多態性通過其虛函數體現。

4、COM接口的作用和意義

COM規范的核心內容是關於接口的定義,雖然COM本身並不復雜,但是圍繞COM接口有很多內容值得仔細探討,包括接口的標識、接口函數的調用習慣、參數處理、接口與對象的關系以及接口與C/C++的關系、COM接口多具有的特性等。

COM定義了一套完整的接口規范,不僅可以彌補API作為組件接口的不足,還從分發揮了組件對象的優勢,並實現了組件對象的多態性。

5、接口定義和標識

從技術上講,接口是包含了一組函數的數據結構,通過這組數據結構,客戶代碼可以調用組件對象的功能。

客戶程序用一個指向接口函數結構的指針來調用接口成員函數。實際上接口指針指向另一個指針pVtable。

接口函數表稱為虛函數表(Virtual Function Table ,簡稱vtable),指向vtable的指針為pVtable。對於一個接口來說,它的虛函數表vtable是確定的。

6、接口設計的問題

在接口成員函數中,字符串變量必須用Unicode字符指針,這是COM規范的要求。

COM API函數使用大多數語言慣用的_stdcall調用習慣。

用C語言定義COM接口,需要有結構體struct定義其接口結構,接口成員函數必須有一個this指針。

用C++語言定義COM接口,因為由C++語言class的實現機理可以看出,COM接口結構中的vtable與class的vtable(類的虛函數表)完全一致,因此,用class描述COM接口是最方便的手段。此時,接口成員函數隱藏了this指針。

class 型接口的說明要比struct 型接口的說明簡捷得多。

7、COM接口與對象的聯系

接口類只是一種描述,並不提供具體的實現過程。如果COM對象要實現接口,則COM對象必須以某種方式把它自身與接口類聯系起來,然後把接口類的指針暴露給客戶程序,於是客戶程序就可以調用對象的接口功能了。

用 class型接口通過把接口指針(this)與對象數據綁定在一起的方法實現對COM接口的支持比較直觀、簡捷易於理解。實際上,也可以采用其他的方法來實現接口,只要接口成員函數中this指針(即接口指針)與對象數據能建立確定的連接,在接口成員函數中可以訪問到對象數據即可。例如,VC++的MFC 庫和ATL(active template library ,活動模板庫)模板庫分別采用了不同的機制來提供對COM接口的支持。

8、接口描述語言IDL

COM 規范在采用OSF的DCE規范描述遠程調用接口IDL(interface description language ,接口描述語言)的基礎上,進行擴展形成了COM接口的描述語言。接口描述語言提供了一種不依賴於任何語言的接口描述方法,因此,它可以成為組件程序和客戶程序之間的共同語言。

COM 規范使用的IDL接口描述語言不僅可用於定義COM接口,同時還定義了一些常用的數據類型,也可以描述自定義的數據結構,對於接口成員函數,我們可以制定每個參數的類型、輸入輸出特性,甚至支持可變長度的數組的描述。VC++提供了MIDL工具,可以把IDL接口描述文件編譯成C/C++兼容的接口描述頭文件(.h)。

9、接口的內存模型

COM對象往往有自己的屬性數據,它們反映對象的狀態,並用於區分不同的對象。對於有多個對象的客戶,數據屬性是不能公用的。

10、接口的特點

二進制特性

接口不變性

繼承性(擴展性):類似於C++中類的繼承性,接口也可以繼承發展,但方式不同。類繼承不僅是說明繼承,也是實現繼承,即派生類可以繼承基類的函數實現,而接口繼承只是說明繼承,即派生的接口只繼承了基接口的成員函數說明,而沒有繼承基接口的實現。類繼承允許多重繼承,但接口繼承只允許單繼承。根據COM規范,所有接口都必須從IUnknown派生,可以直接派生,也可以間接派生。但大多數都是直接派生。OLE系統中,接口最後字母是“2”或“Ex”的,標煤它是一個繼承接口。

多態性:COM對象具有多態性,其通過COM接口體現。

11、IUnknown接口提供了兩個非常重要的特性:生存期控制(使用引用計數)和接口查詢。

12、IUnknown接口引用計數的設置層級

引用計數在組件一級實現則計數分辨率太粗(選擇全局變量),在對象一級實現恰好(使用C++類的成員變量),在接口一級實現則計數分辨率太細(使用類成員變量)。

13、使用引用計數的規則

根據不同場合使用或者傳遞接口指針標量進行分類,並給出相應的規則:

(1)函數的參數中使用接口指針變量。

輸入參數:由於輸入參數由調用函數控制,因此被調用函數執行過程中,接口指針一定保持有效,引用計數不需要改變。

輸出參數:輸出參數是指在被調用函數執行過程中進行賦值的參數,而且被調用函數並沒有用到函數初始化傳進來的值,輸出參數相當於函數的一個返回值。在C/C++語言中,輸出參數為一個指針變量(COM中不使用引用變量)。因為輸出參數相當於在被調用函數中生成了一個新的接口指針變量,因此,在被調用函數返回之前,對輸出參數應該調用AddRef使接口引用計數增1。這條規則也適用於函數返回值為接口指針變量的情況。

輸入-輸出參數:在參數被修改之前,對原來傳進來的接口指針調用Release以使引用計數減1,在參數被修改之後,對新的接口指針變量調用AddRef,以標記對新的接口指針的引用。如果在函數執行過程中參數沒有被修改,則不需要改變。

(2)局部接口指針變量:因為在局部函數塊中,接口指針總是有效的,所以,一個局部接口指針變量被賦了值並調用了接口成員函數,引用計數不需要改變。

(3)全局接口指針變量:把全局接口指針變量作為輸入參數傳給某個函數之前,應該調用AddRef以保證在函數調用中可以使用給接口指針變量,因為它是全局變量,其他的函數有可能會調用Release函數。在函數返回之後應該調用Release函數。

(4)C++中類成員變量為接口指針變量:因為對於類的作用域來講,成員變量相當於全局變量,因此適用於規則(3)。

(5)當以上情形都不適合時,使用以下一般的規則:

在順序執行過程中,如果要對一個接口指針變量賦值,則對賦值後的接口指針變量調用AddRef,並且,如果賦值前的接口指針變量還沒有結束,則賦值前必須對它調用Release以便先結束它的使用。

如果要結束使用一個接口指針變量,以後不再用到它了,則調用Release函數。

14、接口查詢

使用QueryInterface函數查詢接口,其返回值有S_OK、E_NOINTERFACE、E_UNEXPECTED。

15、COM對象的接口原則

(1)對於同一個對象的不同接口指針,查詢得到的IUnknown接口必須完全相同。即每個對象的IUnknown接口指針是唯一的。

(2)接口對稱性。即對一個接口查詢其自身總應該成功。

(3)接口自反性。

(4)接口傳遞性。

(5)接口查詢時間無關性。

16、多接口COM對象的實現方法

在C++語言中有兩種實現方法:一是使用多重繼承,把所支持的接口作為其基類,然後在對象類中實現接口成員函數;二是使用內嵌接口類成員。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved