接口類可以用作不同編程方法递瑰、數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)技術(shù)茎杂、編碼方法起便、命名約定以及不同操作系統(tǒng)環(huán)境之間的橋梁吊宋。事實(shí)上,將傳統(tǒng)C程序移植到對(duì)象世界的最簡單途徑是為C程序中自由漂浮的函數(shù)和數(shù)據(jù)提供接口類啦吧。當(dāng)需要具備不同OS間或不同硬件平臺(tái)間的可移植性時(shí)您觉,接口類將責(zé)無旁貸地為完成這類工作的武器。
1. 接口類詳解
接口類用于為代碼和數(shù)據(jù)提供一個(gè)新的接口授滓,或更改代碼和數(shù)據(jù)的舊接口琳水。它可以用于修改或改進(jìn)另一個(gè)類或一系列類的接口,許多情況下般堆,還可用來給非面向?qū)ο缶幊坦ぷ魈峁┟嫦驅(qū)ο蠼涌诶邕^程庫在孝、OS API淮摔,或者數(shù)據(jù)庫管理系統(tǒng)提供面向?qū)ο蠼涌谒骄凇J褂盟梢宰屃硪粋€(gè)類更易使用,功能更強(qiáng)和橙,更完全仔燕,或者在語義上更正確。
1.1 接口類的類型
作為非面向?qū)ο髷?shù)據(jù)和代碼的封裝器魔招。當(dāng)我們構(gòu)建多線程架構(gòu)技術(shù)時(shí)晰搀,會(huì)使用接口類來封裝提供多線程處理服務(wù)、進(jìn)程控制服務(wù)仆百、進(jìn)程間通信厕隧、文件I/O以及設(shè)備I/O的OS API俄周。它的一個(gè)重要用途是為數(shù)據(jù)和需要操作于該數(shù)據(jù)的函數(shù)提供獨(dú)立域接口吁讨。
a.適配器——修改其它類接口的類
類配器類為其它現(xiàn)在面向?qū)ο箢愄峁┓庋b器。它的目標(biāo)不是添加功能性峦朗,而是提供一個(gè)新接口建丧。一個(gè)典型的例子就是作為標(biāo)準(zhǔn)模板庫一部分的容器適配器。它為標(biāo)準(zhǔn)模板庫中的list波势、vector和deque容易提供了一個(gè)新的公共接口翎朱。另外若只是重命名適配類的成員函數(shù)橄维,則使用內(nèi)聯(lián)(inline)是有利的,它可將重命名的開銷降到最低點(diǎn)拴曲。
b.藍(lán)圖接口類
藍(lán)圖接口類提供一個(gè)接口争舞,但沒有任何實(shí)現(xiàn),它為將來的類提供基礎(chǔ)澈灼。典型情況下竞川,這樣的類不包含數(shù)據(jù),其上的所有成員函數(shù)都為純虛擬(pure∪邸virtual)委乌,而且它的所有基類也為接口類。它們用來計(jì)劃程序員使用該類時(shí)必須實(shí)現(xiàn)哪些成員函數(shù)荣回。它不僅要求實(shí)現(xiàn)一定的函數(shù)遭贸,而且還要求這些函數(shù)有一定的命名約定。
1.2 減小參數(shù)和全局變量的數(shù)量
使用接口類封裝過程代碼和數(shù)據(jù)的一個(gè)重要附帶作用是減少了調(diào)用新成員函數(shù)時(shí)的參數(shù)心软。
2.『敬怠C++沒有多線程處理的關(guān)鍵字
C++是一種被設(shè)計(jì)用于生成(build)和重用(reuse)的語言。在速度和空間效率上删铃,它的性能與C語言是相等的算利。C++語言定義中并不存在并發(fā)或多線程的關(guān)鍵字(這一局面在C++11中得到了改關(guān),通過像atomic_t等類型的引入)泳姐,不過它們都可以在C++中生成效拭。
目前針對(duì)并行處理具有幾種經(jīng)典的硬件模型:
a.單指令多數(shù)據(jù)流(SIMD);∨置搿b. 多指令單數(shù)據(jù)流(MISD)缎患; c. 多指令多數(shù)據(jù)流(MIMD)阎肝;〖酚妗d. 單程序多數(shù)據(jù)流(SPMD)。
并行處理環(huán)境(其中所有的處理器共享單個(gè)地址空間)與每個(gè)處理器擁有各自地址空間的環(huán)境不大一樣风题。對(duì)C++程序員而言判导,面對(duì)如此多要求并行處理的不同類型程序員、而且應(yīng)用的環(huán)境又是如此復(fù)雜沛硅,因此眼刃,僅憑單個(gè)模型,甚至用少量的模型摇肌,是不可能實(shí)現(xiàn)的擂红。于是改而按庫的形式實(shí)現(xiàn)并發(fā),或多線程編程围小。按此種途徑昵骤,可以用庫來實(shí)現(xiàn)所期望的任何模型树碱,而不必強(qiáng)迫每個(gè)C++用戶掌握并行編程。
如果C++中置入了并行處理的特定模型变秦,程序員將限制于抽象機(jī)器所處的表達(dá)力成榜。如果將功能類型建成庫,而不是語言結(jié)構(gòu)蹦玫,那么更改功能的實(shí)現(xiàn)就不必修改編譯器或虛擬機(jī)模型伦连。要知道,現(xiàn)實(shí)世界中經(jīng)常會(huì)引入一些硬件并行化的新模型钳垮,如果采用了關(guān)鍵字的途徑,C++語言的定義就要不斷地修改额港。實(shí)質(zhì)上饺窿,將并行處理和多線程處理推到庫或類庫的高度,C++獲得的是最靈活的處理方式移斩。此時(shí)程序員可以“即插即用”不同的并發(fā)模型肚医。
因?yàn)椋茫袥]有支持多線程處理或進(jìn)程間通信的關(guān)鍵字,所以向瓷,我們必須用類肠套、類庫和應(yīng)用框架的形式來構(gòu)建這種支持。另外我們選擇重用OS代碼猖任∧阒桑可以設(shè)計(jì)IPC類、線程控制類以及進(jìn)程控制類朱躺,讓它們都重用OS代碼刁赖。這些類最終生成一個(gè)接口類,使用它們我們可以構(gòu)建任務(wù)和線程類长搀。使用任務(wù)和線程類宇弛,我們可以構(gòu)建線程和任務(wù)庫,進(jìn)而通過使用線程和任務(wù)庫源请,我們可以構(gòu)建多線程應(yīng)用框架枪芒。
3. 面向?qū)ο蠼涌诘焦艿?/p>
兩種可用的最基本IPC機(jī)制是匿名管道和命名管道。UNIX/Win32/OS/2都支持這些基本IPC谁尸。其中匿名管道的基本功能在每種環(huán)境中都是相同的舅踪,但命名管道在Win32和OS/2中的功能與大部分UNIX環(huán)境中的功能大相徑庭。雖然這些環(huán)境都支持管道良蛮,但系統(tǒng)API對(duì)于這些機(jī)制來說不是面向?qū)ο蟮牧螂虼瞬恢С址庋b和繼承。如果要使用OS”痴颉API來構(gòu)建多線程應(yīng)用框架的基石咬展,必須首先將必需的OS服務(wù)引入對(duì)象世界泽裳。
對(duì)管道的任何面向?qū)ο筇幚矸绞街辽倬哂校祩€(gè)組件:
a.?dāng)?shù)據(jù)緩沖器;∑破拧b.?dāng)?shù)據(jù)緩沖器插入操作涮总; c.?dāng)?shù)據(jù)緩沖器提取操作祷舀;∑俟!d.?dāng)?shù)據(jù)緩沖器創(chuàng)建操作;∩殉丁e.?dāng)?shù)據(jù)緩沖器析構(gòu)操作抛丽。
此外管道還有兩個(gè)終端,一端用于插入數(shù)據(jù)饰豺,另一端則用于提取數(shù)據(jù)亿鲜。這兩個(gè)終端可以在不同的進(jìn)程中使用。通過這兩個(gè)終端冤吨,簡單的管道抽象可以被看作任何類型的IO組件蒿柳。共有兩種創(chuàng)建面向?qū)ο蠊艿赖募夹g(shù),第一種技術(shù)使用面向?qū)ο蠊ぞ咪鲶。椋铮螅簦颍澹幔韺哟我呀?jīng)為我們提供了這些工具垒探;第二種則使用復(fù)合和fstream對(duì)象來創(chuàng)建pstream對(duì)象(管道類)。
iostream類層次的主要組件可以描述為3種類:緩沖器組件(buffer〉±睢component)圾叼、翻譯組件(translation component)以及狀態(tài)組件(state∞囫component)褐奥。緩沖器組件用作傳送中字節(jié)的保存區(qū),翻譯組件負(fù)責(zé)為程序員提供字節(jié)流信號(hào)量翘簇,其中的所有IO撬码,不論其源與目標(biāo)是哪里,都被看作字節(jié)流版保。狀態(tài)組件封裝面向?qū)ο罅鞯臓顟B(tài)呜笑,它顯示可用于緩沖器組件中數(shù)據(jù)字節(jié)的格式類型,還顯示流是否在追加(append)彻犁、創(chuàng)建叫胁、排它性讀或排它性寫模式已經(jīng)被打開,或者數(shù)字是否被解釋成十六進(jìn)制汞幢、八或二進(jìn)制等驼鹅;還可用于判斷對(duì)緩沖器組件的IO操作錯(cuò)誤狀態(tài)。
可以看出,抽象管道的五個(gè)基本組件在iostream中已經(jīng)實(shí)現(xiàn)输钩,我們只需要決定如何才能結(jié)合邏輯輸入和輸出端口的概念與iostream豺型。
iostream類中共有三種緩沖器類型如下:
a. streambuf:內(nèi)存區(qū)域集,具有大量定義內(nèi)存區(qū)域行為的受保護(hù)方法买乃,它提供了與輸入姻氨、輸出設(shè)備間發(fā)送數(shù)據(jù)的接口;
b.〖粞椤strstreambuf:繼承了streambuf類肴焊。它定義了內(nèi)存緩沖的基本行為。緩沖器按FIFO列表或字節(jié)數(shù)組實(shí)現(xiàn)功戚;
c.∪⒕臁filebuf:繼承了streambuf類。它為同文件間的輸入或輸出提供了一個(gè)緩沖器啸臀。get/put指針是一個(gè)指示當(dāng)前讀取或?qū)懭胄畔⑽恢玫闹羔槨?/p>
ifstream和ofstream兩者都包含filebuf類届宠。fstream類繼承了ifstream和ofstream,所以它也包含filebuf類壳咕。因此,我們可以使用fstream類家庭的任何一個(gè)類來幫助我們創(chuàng)建面向?qū)ο蠊艿拦ぞ咄绮觥N覀兛梢酝ㄟ^構(gòu)造函數(shù)谓厘,或通過attach()成員函數(shù)連接pipe()系統(tǒng)調(diào)用返回的文件描述符。
使用提取器和插入器進(jìn)行自動(dòng)格式翻譯是使用fstream類家族與管道通信的一個(gè)主要優(yōu)點(diǎn)寸谜。使用用戶自定義提取器和插入器的能力克服了管道編程中碰到的一些困難竟稳。fstream類家族也可以使用read()和write()成員函數(shù)來讀取管道數(shù)據(jù)和寫入數(shù)據(jù)。
我們也可以通過ostream_iterator和istream_iterator來使用管道熊痴。這些迭代器是一般性他爸、面向?qū)ο蟮闹羔槨?/p>
4. 使用接口類來實(shí)現(xiàn)面向?qū)ο竺艿?/p>
4.1 C/S架構(gòu)及術(shù)語
當(dāng)進(jìn)程使用匿名管道進(jìn)行通信時(shí),進(jìn)程是關(guān)聯(lián)的果善。而通過名字打開管道的進(jìn)程稱做客戶進(jìn)程诊笤。服務(wù)器進(jìn)程可以有多個(gè)使用管道的客戶進(jìn)程。服務(wù)器進(jìn)程負(fù)責(zé)建立命名管道的屬性巾陕。
4.2 名字包含哪些內(nèi)容
在UNIX環(huán)境中讨跟,無關(guān)聯(lián)進(jìn)程可使用命名管道,不過這些進(jìn)程必須位于同一臺(tái)計(jì)算機(jī)上鄙煤。在Win32和OS/2環(huán)境中晾匠,命名管道可以通過網(wǎng)絡(luò)來訪問。
基本命名管道的最終抽象至少具備以下組件:
a.管道名字梯刚;b.訪問權(quán)限凉馆;c.打開模式;d.管道模式;e.輸入端口澜共;f.輸出端口向叉;g.輸入端口大小咳胃;h.輸出端口大兄部怠;i.數(shù)據(jù)緩沖器展懈;j.數(shù)據(jù)緩沖器插入損傷;k.數(shù)據(jù)緩沖器提取操作销睁;l.數(shù)據(jù)緩沖器創(chuàng)建操作;m.數(shù)據(jù)緩沖器析構(gòu)操作存崖。
如果在UNIX環(huán)境中需要與Win32環(huán)境中相似的功能冻记,則應(yīng)當(dāng)使用socket。
4.3 命名管道和iostream復(fù)合
在構(gòu)建命名管道對(duì)象包含Pstream類期間使用復(fù)合(composition)来惧。通過與fstream對(duì)象的包容關(guān)系冗栗,npstream類是命名管道功能與iostream提供的IO面向?qū)ο竽P偷暮铣伞?/p>
4.4 npstream接口類
此類中包含兩個(gè)構(gòu)造函數(shù)。其中服務(wù)器進(jìn)程使用第一個(gè)構(gòu)造函數(shù)構(gòu)建命名管道供搀。這個(gè)構(gòu)造函數(shù)包含對(duì)DosCreateNPipe()的實(shí)際調(diào)用隅居。創(chuàng)建管道后,使用DosConnectNPipe()函數(shù)將它設(shè)置成監(jiān)聽模式(listening mode)葛虐。一旦將管道放入監(jiān)聽模式后胎源,通過調(diào)用attach()成員函數(shù)建立與fstream對(duì)象NamedPipe的連接。然后客戶進(jìn)程使用第二個(gè)構(gòu)造函數(shù)打開與管道的連接屿脐,通過傳統(tǒng)的打開調(diào)用來打開命名管道即DosOpen函數(shù)涕蚤。
4.5 命名管道與STL istream_iterator和ostream_iterator
同樣命名管道也可以通過iostream對(duì)象進(jìn)行istream_iterator, ostream_iterator連接。這樣大部分可以與istream_iterator或ostream_iterator使用的STL算法也可以通過iostream連接應(yīng)用于命名管道的诵。為了讓npstream類用于復(fù)制万栅,必須添加異常處理。事件互斥量和其它同步變量也應(yīng)當(dāng)用于協(xié)調(diào)管道的應(yīng)用西疤。