slide1
Download
Skip this Video
Download Presentation
第十五章

Loading in 2 Seconds...

play fullscreen
1 / 43

第十五章 - PowerPoint PPT Presentation


  • 147 Views
  • Uploaded on

第十五章. 樣板( Template ). 第十五章 樣板( Template ). 樣板是 C++ 為了方便能夠快速生產程式而提供的新功能,在最初期的 C++ 版本中,並不提供樣板機制。所謂樣板( Template ),就是讓某些特定功能的程式如同板模般,當我們需要大量使用該功能時,直接由編譯器代為改變程式細節,以符合輸入的資料型態。

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' 第十五章' - bruno-osborn


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide1

第十五章

樣板(Template)

template
第十五章樣板(Template)
  • 樣板是C++為了方便能夠快速生產程式而提供的新功能,在最初期的C++版本中,並不提供樣板機制。所謂樣板(Template),就是讓某些特定功能的程式如同板模般,當我們需要大量使用該功能時,直接由編譯器代為改變程式細節,以符合輸入的資料型態。
  • 因此,在現代化的程式設計中,大多將函式或類別設計為樣板,避免撰寫相同功能但資料型態不同的程式。在正式介紹樣板之前,請讀者注意一點,繼承與樣板都能增進程式碼重複使用率及減少程式開發時程,但樣板的對象是固定是類別和函式,而繼承僅限於類別,兩者在許多方面有根本上的不同。
slide3
大綱
  • 15.1 什麼是樣板?
  • 15.2 函式樣板
    • 15.2.1 單一保留資訊的函式樣板
    • 15.2.2 多保留資訊的函式樣板
  • 15.3 類別樣板
  • 15.4 樣板的具現
  • 15.5 本章回顧
slide4
15.1 什麼是樣板?
  • 在C語言中,程式設計師常常會遇到一個麻煩的問題,就是即使函式需求相同,但必須針對不同資料型態,設計不同的函式,例如我們想要求出絕對值,就必須設計成兩個名稱不同的函式,如下範例。
slide5
15.1 什麼是樣板?
  • 在初期的C++中,上述情況獲得改善,我們可以利用函式覆載(Overload)功能,將函式名稱設定為相同的abs,只要引數內容不同即可,如下範例。
  • 雖然C++提供了覆載函式來解決函式名稱的問題,但仍無法解決撰寫重複程式碼的問題(雖然通常只需要複製程式碼並略為修改即可),而後期的C++則提供了樣板來解決上述問題。樣板允許保留一些資料,等到實際使用樣板時,才於編譯時期,由編譯器自行複製程式內容。
slide6
15.1 什麼是樣板?
  • 事實上,樣板可分為兩大類:函式樣板(Function Template)及類別樣板(Class Template),而其目的則分別是為了加強的函式和類別的開發速度。有了樣板,我們只需預先設計一個通用的板模,然後當我們需要設計類似功能的函式或類別時,就套用這個樣板,並設定相關必要的資訊就可以了。
slide7
15.1 什麼是樣板?
  • 舉例來說,假設我們有一個交換函式swap函式如下,它可以作整數資料的交換。
  • 在設計上述的swap函式樣板時,我們可以將程式碼內的int資料型態設定為保留資訊,當我們作整數交換時,只要套用這個樣板,並設定資料型態為int;當我們需要作字元交換,也是同樣可以套用這個樣板,只要將資料型態設定為char即可。換句話說,一個經過設計的樣板,可以讓我們節省很多撰寫類似程式碼的時間,因為編譯器將代為處理套用樣板時的函式轉換手續。
slide8
15.2 函式樣板
  • C++的樣板有函式樣板與類別樣板兩種,我們先從簡單的函式樣板開始介紹,我們將函式樣板的宣告分為兩大類語法來加以介紹,即單一保留資訊的函式樣板與多保留資訊的函式樣板。
15 2 1
15.2.1 單一保留資訊的函式樣板
  • 單一保留資訊的函式樣板宣告與定義:
    • 單一保留資訊的函式樣板宣告語法如下:
    • 單一保留資訊的函式樣板定義語法如下:
    • 語法說明:
      • (1)N是欲保留的資訊,也就是能被替換的資料型態,編譯器將依據呼叫時的資料型態,產生對應的變化。
      • (2)class關鍵字可改為typename。
      • (3)函式回傳型態也可以宣告為N(保留資訊)。

template <class N> 函式回傳型態 函式名稱(N,N,...);

template <class N> 函式回傳型態 函式名稱(N 引數1,N 引數2,...)

{

...樣板內容…

}

15 2 11
15.2.1 單一保留資訊的函式樣板
      • (4)由於C++是自由格式,因此常見到將宣告列改為兩行的格式,如下定義格式:
  • 【觀念及實用範例15-1】:實作swap函式樣板,並在呼叫函式樣板時,傳入不同的資料型態。
  • 範例15-1:ch15_01.cpp(檔案位於隨書光碟 ch15\ch15_01.cpp)。

template <class N>

函式回傳型態 函式名稱(N 引數1,N 引數2,...)

{

...樣板內容…

}

15 2 13
15.2.1 單一保留資訊的函式樣板

樣板(套用char資料型態):

a1 = i , b1 = j

Swap:

a1 = j , b1 = i

-------------------------

樣板(套用int資料型態):

a2 = 25 , b2 = 56

Swap:

a2 = 56 , b2 = 25

-------------------------

樣板(使用double資料型態):

a3 = 0.7 , b3 = 9.3

Swap:

a3 = 9.3 , b3 = 0.7

  • 執行結果
  • 範例說明:
    • (1)第11行,函式樣板宣告。第13~20行,函式樣板定義。對照上述範例,我們可以發現,定義中,僅將原本的int改寫為保留資訊T而已。
15 2 14
15.2.1 單一保留資訊的函式樣板
  • (2)當我們宣告swap為函式樣板後,每一次呼叫swap函式時,只要輸入正確的資料時,編譯器會先判斷是否為正確的指標或正確的資料型態,然後依照所判斷的資料型態自動產生相對應的程式碼。例如為了因應第35行的呼叫,編譯器會自動將樣板複製並取代保留資訊,成為下列程式碼:
15 2 15
15.2.1 單一保留資訊的函式樣板
  • (3)當我們在呼叫函式樣板的時候,代入的引數會決定這個函式樣板的內部資料型態。因此在第35行,編譯器判斷及處理的流程如下圖。

圖15-1 編譯器判斷及處理函式樣板的流程

15 2 2
15.2.2 多保留資訊的函式樣板
  • 有時候,我們想要保留的資訊不只一個的時候,C++仍允許我們建立樣板,只要將欲保留的資訊一一宣告即可,如下語法:
    • 多保留資訊的函式樣板宣告語法如下:
    • 多保留資訊的函式樣板定義語法如下:
    • 語法說明:
      • (1)N1、N2…是欲保留的資訊,引數型態則可宣告為這些保留資訊的任一種。
      • (2)class關鍵字可改為typename。
      • (3)函式回傳型態也可以宣告為N1或N2…….(即保留資訊之一)。

template <class N1,class N2,……….>

函式回傳型態 函式名稱(N1或N2或…,N1或N2或…,...);

template <class N1,class N2,………>

函式回傳型態 函式名稱(N1或N2或… 引數1, N1或N2或… 引數2,..);

{

...樣板內容…

}

15 2 21
15.2.2 多保留資訊的函式樣板
  • (4)假設我們有兩個保留資訊及兩個引數,則下列是一個合法的宣告範例:
  • (5)然而我們常常在使用函式樣板時,會不小心使用錯誤的語法,例如下列幾個錯誤範例:
15 2 22
15.2.2 多保留資訊的函式樣板
  • 【觀念範例15-2】:函式樣板中包含多個保留資訊。
  • 範例15-2:ch15_02.cpp(檔案位於隨書光碟 ch15\ch15_02.cpp)。
15 2 23
15.2.2 多保留資訊的函式樣板
  • 執行結果

m= 3,p=5, m的p次方=243

n=1.5,p=5, n的p次方=7.59375

15 2 24
15.2.2 多保留資訊的函式樣板
  • 範例說明:
    • (1)第11行,函式樣板宣告。第13~21行,函式樣板定義。我們在樣板中保留了兩項資訊,T1與T2,其中T2只用在引數宣告與函式定義,而T1則同時用在函式回傳值、引數宣告與函式定義。
    • (2)在第27行呼叫power(m,p)時,它將會建構下列的程式碼。
15 2 25
15.2.2 多保留資訊的函式樣板
    • (3)在第28行呼叫power(n,p)時,它將會建構下列的程式碼。
  • 對於T1被引數及回傳值同時引用的部分,或許讀者會產生疑惑,在上述說明中,似乎編譯器只要確定引數的資料型態後,就決定了保留資訊應該被取代為哪一種資料型態。例如呼叫power(m,p)時,T1被確認為int,在呼叫power(n,p)時,T1被確認為double。而若我們將回傳值使用另一種型態來接收時,例如int y=power(n,p);,會是什麼樣的狀況呢?答案是會產生警告訊息,編譯器仍將T1認為是double,因此回傳double資料型態的資料,當然最終結果y仍舊是被強制轉型的整數,在上例中,y將會是7。
slide22
15.3 類別樣板
  • 樣板除了可以應用於函式外,也可以應用於類別,這樣的類別稱之為『類別樣板』。經過樣板化的類別,其內的成員函式與成員變數可適用於所有的資料型態,只要將某些資訊宣告為保留資訊即可。類別樣板的宣告及定義與函式樣板大同小異,運作原理也差不多,如下所述。
  • 首先讓我們先來看看類別樣板的標準宣告格式如下:
    • 類別樣板的定義語法如下:

template <class N> class 類別名稱

{

保護等級:

函式回傳型態 函式名稱(N 引數1,N 引數2,...); //成員函式

...

N 變數名稱; //成員變數

...

}

slide23
15.3 類別樣板
  • 類別樣板的成員函式,若定義於類別外部,則語法如下:
  • 類別樣板產生物件語法:
  • 語法說明:
    • (1)N是欲保留的資訊,如果保留資訊不只一個,也可以按照<class N1,class N2,…>等格式擴充。

template <class N> 函式回傳型態 類別樣板名稱 <N>::成員函式名稱( )

{

…. 函式定義內容…

}

類別樣板名稱 <保留資訊的資料型態> 物件名稱;

slide24
15.3 類別樣板
  • (2)< >內的class關鍵字可改為typename。
  • (3)函式回傳型態也可以宣告為保留資訊之一。
  • (4)宣告類別樣板內的成員函式,並在類別外部定義成員函式時,除了必須在前面加上template <class N>,原本的類別名稱,應該改為『類別樣板名稱 <N>』。
  • (5)利用類別樣板產生物件時,也同樣必須加上保留資訊的資料型態,例如<int>、<float>。
  • (6)常見的類別樣板宣告錯誤範例如下:
  • 錯誤範例
    • 和函式樣板一樣的限制,類別樣板的引數型態定義不可以在類別中重複使用,如下例的Type。
slide26
15.3 類別樣板
  • 【觀念及實用範例15-3】:使用類別樣板,使得氣泡排序法可以接受各種資料型態。
  • 範例15-3:ch15_03.cpp(檔案位於隨書光碟 ch15\ch15_03.cpp)。
slide30
15.3 類別樣板
  • 執行結果

----整數陣列已建立----

請輸入第0個元素:24

請輸入第1個元素:17

請輸入第2個元素:32

請輸入第3個元素:19

24 17 32 19

--------排序後-------

17 19 24 32

=========================

----浮點數陣列已建立----

請輸入第0個元素:15.67

請輸入第1個元素:28.43

請輸入第2個元素:17.52

請輸入第3個元素:12.88

15.67 28.43 17.52 12.88

--------排序後-------

12.88 15.67 17.52 28.43

slide31
15.3 類別樣板
  • 範例說明:
    • (1)第11行,類別樣板宣告。第13~23行,類別樣板定義。我們在樣板宣告保留資訊為T。
    • (2)在第70行,類別樣板建立ObjX物件時,T會被指定為int後,由編譯器產生對應的類別程式碼,然後才產生物件。
    • (3)在第78行,類別樣板建立ObjY物件時,T會被指定為double後,由編譯器產生對應的類別程式碼,然後才產生物件。
slide32
15.4 樣板的具現
  • 在上述的範例說明中,我們不斷地說明,當呼叫函式樣板時,或透過類別樣板宣告物件時,編譯器都會產生一些程式碼。事實上,這個由編譯器自動執行的動作稱之為『樣板的具現(instantiation)』。
    • 在編譯時期,編譯器會將樣板依照所給予不同型別的引數,建構出對應的函式或類別。若是經由函式呼叫而造成函式建構的動作,我們稱之為函式樣板的具現;而經過類別的生成物件而造成類別建構的動作,就稱為類別樣板的具現。函式樣板必須在具現後,才能被呼叫,而類別樣板則是必須在具現後,才能夠產生物件。
    • 函式樣板的具現與類別樣板的具現可以是獨立的,但也可以有先後關係。這通常發生在類別樣板內又定義了成員函式樣板時。
slide33
15.4 樣板的具現
  • 雖然類別樣板已經能夠提高非常好的程式開發效率,但如果成員函式的相似性也很高,我們也可以利用函式樣板進一步定義類別樣板的成員函式,使得程式重複性更低。而此時,定義型態的過程將具有先後的關聯性。
    • 我們透過範例15-4,說明編譯器對於樣板的定義流程。範例15-4,將修改自範例15-3,將互換資料另外獨立出來成為swap成員函式,並使用函式樣板來宣告swap函式。
  • 【觀念及實用範例15-4】:修改範例15-4,結合類別樣板和函式樣板。
  • 範例15-4:ch15_04.cpp(檔案位於隨書光碟 ch15\ch15_04.cpp)。
slide38
15.4 樣板的具現
  • 執行結果:(同範例15-3)
  • 範例說明:
    • 在類別樣板內,我們又宣告了一個成員函式樣板swap(在第20~26行)。並且在BubbleSort成員函式的第65行呼叫這個成員函式。整個編譯器在編譯過程如下:
      • Step1: 在第76行,遇到Sort <int> ObjX;,先決定保留資訊T的資料型態為int。
      • Step2: 此時T變成了輸入引數資料型態為int的Sort類別,也就是必須將T替換為int產生類別的程式碼。
      • Step3: 但編譯器欲產生類別的程式碼時,發現定義了一個成員函式樣板,因此,編譯器必須保留該位置,等到決定BubbleSort成員函式的內容時,找到swap函式樣板的呼叫時,才產生swap函式的程式碼,完成swap函式的具現後,才能夠完成Sort類別的具現。換句話說,具現的過程有如一個堆疊(先進後出),當遇到另一個更深層的具現時,則必須將更深層具現完成後,才能完成較外圍的具現。
slide39
15.5 本章回顧
  • 在本章中,我們介紹了C++提供的新功能-『樣板』,善用樣板可以讓我們更有效率地開發中大型專案,減少撰寫相似程式碼的機會,本章重點整理如下:
    • (1)C++提供了樣板來解決相似程式碼浪費開發時程的問題。樣板允許保留一些資料,等到實際使用樣板時,才於編譯時期,由編譯器自行複製程式內容。
    • (2)樣板可分為兩大類:函式樣板(Function Template)及類別樣板(Class Template)。兩者運作的方式和觀念差不多。
    • (3)函式樣板的語法如下:
      • 單一保留資訊的函式樣板宣告語法如下:
      • 單一保留資訊的函式樣板定義語法如下:

template <class N> 函式回傳型態 函式名稱(N,N,...);

template <class N> 函式回傳型態 函式名稱(N 引數1,N 引數2,...)

{

...樣板內容…

}

slide40
15.5 本章回顧
  • 多保留資訊的函式樣板宣告語法如下:
  • 多保留資訊的函式樣板定義語法如下:

template <class N1,class N2,……….>

函式回傳型態 函式名稱(N1或N2或…,N1或N2或…,...);

template <class N1,class N2,………>

函式回傳型態 函式名稱(N1或N2或…. 引數1, N1或N2或…. 引數2,...);

{

...樣板內容…

}

slide41
15.5 本章回顧
  • (4)類別樣板的相關語法如下:
    • 類別樣板的定義語法如下:
    • 類別樣板的成員函式,若定義於類別外部,則語法如下:

template <class N> class 類別名稱

{

保護等級:

函式回傳型態 函式名稱(N 引數1,N 引數2,...); //成員函式

...

N 變數名稱; //成員變數

...

}

template <class N> 函式回傳型態 類別樣板名稱 <N>::成員函式名稱( )

{

….函式定義內容…

}

slide42
15.5 本章回顧
    • 類別樣板產生物件語法:
  • (5)在編譯時期,編譯器會將樣板依照所給予不同型別的引數,建構出對應的函式或類別,這個由編譯器自動執行的動作稱之為『樣板的具現(instantiation)』。發生的時機則發生於函式樣板的呼叫以及類別樣板產生物件時。
  • (6)在類別樣板內也可以再定義成員函式的樣板。

類別樣板名稱 <保留資訊的資料型態> 物件名稱;

ad