泛型演算法的設計(1)
前言:泛型演算法獨立於操作的容器且與要操作的元素型別無關,達到了函式彈性設計的最大化,下面我們一步步的實現乙個泛型演算法;
1.有一天,老闆交給你乙個任務,要你程式設計完成如下工作,給定乙個儲存整數的vector,及乙個整數,如果此值存在於vector內,我們必須返回乙個指標指向該值;反之則返回0,表示此值不在vector內;
int find(const vector&vec, int value)
注:當我們實現乙個搜尋函式且用指標為返回值時,我們通常返回0值來標識搜尋失敗;
任務完成的如此順利,以至於你有些沾沾自喜,過了一段時間老闆讓你在儲存字串的vector中查詢一字串,這是你開始反思之前那段**,發現他解決的問題很狹隘,就想從新設計乙個新的函式,不僅可以處理整數,也可以處理任何型別;
2.將find()用function template的形式呈現
template
elemtype* find(const vector&vec, elemtype value)
大功告成,欣喜之餘,新任務也接踵而來,這次需要處理在array中查詢一元素,這樣需要編寫一函式可以同時處理vector,array的元素,用過載固然可行,但略顯笨拙;
這次問題有點棘手,我們的設計思想是將元素傳入函式,但不指明vector或array,即設法使函式獨立於要操作的容器,下面我們一一著手解決;
3.在不指明array的情形下將元素傳入find();
我們的設計思路是傳遞兩個指標,第乙個指標是要處理的第乙個元素,最後乙個指標是要處理的最後乙個元素的下乙個位址(充當哨兵的作用);
template
elemtype* find(const elemtype *first, const elemtype *last, elemtype value)
注:當我們提領指標時,一定要確保其值並非為0;
4.用同樣的思路對vector中的元素進行超找;
因為vector可以為空的,而當我們對乙個空的vector進行&vec[vec.size()]運算時會產生乙個執行時錯誤,故我們在呼叫函式前要先確定函式不為空,即每次呼叫find()需先判斷:
if(!vec.empty())
...但這種函式對呼叫者是不友好的,因此我們定義兩個內聯函式begin(),end()分別返回vector的第乙個元素的位址和最後乙個元素的下乙個位址,同時檢測vector是否為空;
template
inline elemtype* begin(const vector&vec)
template
inline end(const vector&vec)
以這兩個函式為基礎,我們可以完成乙個看似完美的設計:
find(begin(vec),end(vec),seachvalue);
到這裡我們完成乙個比較泛型的演算法,獨立與要處理的元素即可以處理int,string,double...,且一定程度上獨立與要操作的容器,即可處理array,vector,開始有人擊節相慶
了...
可是我們忽略了支援這個函式正常執行的潛在的限制;
1.指標可以通過算術運算遍歷要處理的元素;
2.要處理的元素定義了==操作符;
下面我們對這兩個限制條件進行進一步泛化,首先看第乙個限制條件,當我們操作list容器時就力不從心了,因為list容器的元素以一組指標互相鏈結,不能通過++運算遍歷,
這樣帶了的乙個問題是,通過array,vector,list指標遍歷容器元素的底層執行方式大相徑庭,我們解決的思路是:將通過指標遍歷容器元素的行為抽象出來,在底層指標之上提供一層抽象機制,
使其對程式設計師透明,我們通過iterator實現這層抽象;
我們設計乙個iterator class提供內建的++,*,==,!=運算子,使其與指標有一樣的功能;
最終我們用iterator取代指標且取消原先陣列的下表操作改用提領操作,實現乙個真正意義上的泛型演算法,其獨立於操作的容器,獨立於操作的元素型別;
template
iteratortype find(iteratortype first, iteratortype last,
const elemtype value)
總結:抽象,透明的思想是計算機中乙個重要的設計思想,通過不同層次的抽象,為不同層次的使用者提供了乙個透明的介面,當抽象到最後,面對終端使用者時,
提供給普通大眾的乙個滑鼠操作的視窗選單介面,
迭代器是使用抽象透明設計思想典型例子,在面向程式設計師的這一層次,迭代器將指針對順序表及鍊錶的遍歷操作抽象出來,供程式設計師直接通過++,
--,==等指標運算,而不用考慮具體的底層中通過指標超找下乙個元素的方式。
泛型的使用1
泛型只在編譯期間有效,並且在編譯期間會驗證傳入的值是否為泛型型別的值,如果不是對應泛型的值,將會報錯 此時的建構函式的值應該是泛型的型別的值,也就是string型別的值,否則會報錯。2.如下圖說明了,泛型在編譯成class檔案會被擦除,也就是執行的是同乙個class檔案,此處和jvm的類載入相關。不...
設計乙個泛型演算法
演算法的目的很簡單,找出小於 大於 elem size的元素並列印.先貼上 include algorithm 泛型演算法 include functional function object include vector include iostream using namespace std t...
泛型筆記1
1.collectioncs 不是collectionco 的子型別 2.collection extends number 萬用字元上限是number add 方法受限,只能將number的子類物件加入collection get 方法的結果是number物件 任意number的子型別都可轉換成n...