第十五章
This presentation is the property of its rightful owner.
Sponsored Links
1 / 43

第十五章 PowerPoint PPT Presentation


  • 105 Views
  • Uploaded on
  • Presentation posted in: General

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

Download Presentation

第十五章

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


6982544

第十五章

樣板(Template)


Template

第十五章樣板(Template)

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

  • 因此,在現代化的程式設計中,大多將函式或類別設計為樣板,避免撰寫相同功能但資料型態不同的程式。在正式介紹樣板之前,請讀者注意一點,繼承與樣板都能增進程式碼重複使用率及減少程式開發時程,但樣板的對象是固定是類別和函式,而繼承僅限於類別,兩者在許多方面有根本上的不同。


6982544

大綱

  • 15.1什麼是樣板?

  • 15.2函式樣板

    • 15.2.1單一保留資訊的函式樣板

    • 15.2.2多保留資訊的函式樣板

  • 15.3類別樣板

  • 15.4樣板的具現

  • 15.5本章回顧


6982544

15.1什麼是樣板?

  • 在C語言中,程式設計師常常會遇到一個麻煩的問題,就是即使函式需求相同,但必須針對不同資料型態,設計不同的函式,例如我們想要求出絕對值,就必須設計成兩個名稱不同的函式,如下範例。


6982544

15.1什麼是樣板?

  • 在初期的C++中,上述情況獲得改善,我們可以利用函式覆載(Overload)功能,將函式名稱設定為相同的abs,只要引數內容不同即可,如下範例。

  • 雖然C++提供了覆載函式來解決函式名稱的問題,但仍無法解決撰寫重複程式碼的問題(雖然通常只需要複製程式碼並略為修改即可),而後期的C++則提供了樣板來解決上述問題。樣板允許保留一些資料,等到實際使用樣板時,才於編譯時期,由編譯器自行複製程式內容。


6982544

15.1什麼是樣板?

  • 事實上,樣板可分為兩大類:函式樣板(Function Template)及類別樣板(Class Template),而其目的則分別是為了加強的函式和類別的開發速度。有了樣板,我們只需預先設計一個通用的板模,然後當我們需要設計類似功能的函式或類別時,就套用這個樣板,並設定相關必要的資訊就可以了。


6982544

15.1什麼是樣板?

  • 舉例來說,假設我們有一個交換函式swap函式如下,它可以作整數資料的交換。

  • 在設計上述的swap函式樣板時,我們可以將程式碼內的int資料型態設定為保留資訊,當我們作整數交換時,只要套用這個樣板,並設定資料型態為int;當我們需要作字元交換,也是同樣可以套用這個樣板,只要將資料型態設定為char即可。換句話說,一個經過設計的樣板,可以讓我們節省很多撰寫類似程式碼的時間,因為編譯器將代為處理套用樣板時的函式轉換手續。


6982544

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 12

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


    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。


  • 6982544

    15.3類別樣板

    • 樣板除了可以應用於函式外,也可以應用於類別,這樣的類別稱之為『類別樣板』。經過樣板化的類別,其內的成員函式與成員變數可適用於所有的資料型態,只要將某些資訊宣告為保留資訊即可。類別樣板的宣告及定義與函式樣板大同小異,運作原理也差不多,如下所述。

    • 首先讓我們先來看看類別樣板的標準宣告格式如下:

      • 類別樣板的定義語法如下:

    template <class N> class 類別名稱

    {

    保護等級:

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

    ...

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

    ...

    }


    6982544

    15.3類別樣板

    • 類別樣板的成員函式,若定義於類別外部,則語法如下:

    • 類別樣板產生物件語法:

    • 語法說明:

      • (1)N是欲保留的資訊,如果保留資訊不只一個,也可以按照<class N1,class N2,…>等格式擴充。

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

    {

    …. 函式定義內容…

    }

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


    6982544

    15.3類別樣板

    • (2)< >內的class關鍵字可改為typename。

    • (3)函式回傳型態也可以宣告為保留資訊之一。

    • (4)宣告類別樣板內的成員函式,並在類別外部定義成員函式時,除了必須在前面加上template <class N>,原本的類別名稱,應該改為『類別樣板名稱 <N>』。

    • (5)利用類別樣板產生物件時,也同樣必須加上保留資訊的資料型態,例如<int>、<float>。

    • (6)常見的類別樣板宣告錯誤範例如下:

    • 錯誤範例

      • 和函式樣板一樣的限制,類別樣板的引數型態定義不可以在類別中重複使用,如下例的Type。


    6982544

    15.3類別樣板


    6982544

    15.3類別樣板

    • 【觀念及實用範例15-3】:使用類別樣板,使得氣泡排序法可以接受各種資料型態。

    • 範例15-3:ch15_03.cpp(檔案位於隨書光碟 ch15\ch15_03.cpp)。


    6982544

    15.3類別樣板


    6982544

    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


    6982544

    15.3類別樣板

    • 範例說明:

      • (1)第11行,類別樣板宣告。第13~23行,類別樣板定義。我們在樣板宣告保留資訊為T。

      • (2)在第70行,類別樣板建立ObjX物件時,T會被指定為int後,由編譯器產生對應的類別程式碼,然後才產生物件。

      • (3)在第78行,類別樣板建立ObjY物件時,T會被指定為double後,由編譯器產生對應的類別程式碼,然後才產生物件。


    6982544

    15.4樣板的具現

    • 在上述的範例說明中,我們不斷地說明,當呼叫函式樣板時,或透過類別樣板宣告物件時,編譯器都會產生一些程式碼。事實上,這個由編譯器自動執行的動作稱之為『樣板的具現(instantiation)』。

      • 在編譯時期,編譯器會將樣板依照所給予不同型別的引數,建構出對應的函式或類別。若是經由函式呼叫而造成函式建構的動作,我們稱之為函式樣板的具現;而經過類別的生成物件而造成類別建構的動作,就稱為類別樣板的具現。函式樣板必須在具現後,才能被呼叫,而類別樣板則是必須在具現後,才能夠產生物件。

      • 函式樣板的具現與類別樣板的具現可以是獨立的,但也可以有先後關係。這通常發生在類別樣板內又定義了成員函式樣板時。


    6982544

    15.4樣板的具現

    • 雖然類別樣板已經能夠提高非常好的程式開發效率,但如果成員函式的相似性也很高,我們也可以利用函式樣板進一步定義類別樣板的成員函式,使得程式重複性更低。而此時,定義型態的過程將具有先後的關聯性。

      • 我們透過範例15-4,說明編譯器對於樣板的定義流程。範例15-4,將修改自範例15-3,將互換資料另外獨立出來成為swap成員函式,並使用函式樣板來宣告swap函式。

    • 【觀念及實用範例15-4】:修改範例15-4,結合類別樣板和函式樣板。

    • 範例15-4:ch15_04.cpp(檔案位於隨書光碟 ch15\ch15_04.cpp)。


    6982544

    15.4樣板的具現


    6982544

    15.4樣板的具現


    6982544

    15.4樣板的具現


    6982544

    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類別的具現。換句話說,具現的過程有如一個堆疊(先進後出),當遇到另一個更深層的具現時,則必須將更深層具現完成後,才能完成較外圍的具現。


    6982544

    15.5本章回顧

    • 在本章中,我們介紹了C++提供的新功能-『樣板』,善用樣板可以讓我們更有效率地開發中大型專案,減少撰寫相似程式碼的機會,本章重點整理如下:

      • (1)C++提供了樣板來解決相似程式碼浪費開發時程的問題。樣板允許保留一些資料,等到實際使用樣板時,才於編譯時期,由編譯器自行複製程式內容。

      • (2)樣板可分為兩大類:函式樣板(Function Template)及類別樣板(Class Template)。兩者運作的方式和觀念差不多。

      • (3)函式樣板的語法如下:

        • 單一保留資訊的函式樣板宣告語法如下:

        • 單一保留資訊的函式樣板定義語法如下:

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

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

    {

    ...樣板內容…

    }


    6982544

    15.5本章回顧

    • 多保留資訊的函式樣板宣告語法如下:

    • 多保留資訊的函式樣板定義語法如下:

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

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

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

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

    {

    ...樣板內容…

    }


    6982544

    15.5本章回顧

    • (4)類別樣板的相關語法如下:

      • 類別樣板的定義語法如下:

      • 類別樣板的成員函式,若定義於類別外部,則語法如下:

    template <class N> class 類別名稱

    {

    保護等級:

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

    ...

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

    ...

    }

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

    {

    ….函式定義內容…

    }


    6982544

    15.5本章回顧

    • 類別樣板產生物件語法:

  • (5)在編譯時期,編譯器會將樣板依照所給予不同型別的引數,建構出對應的函式或類別,這個由編譯器自動執行的動作稱之為『樣板的具現(instantiation)』。發生的時機則發生於函式樣板的呼叫以及類別樣板產生物件時。

  • (6)在類別樣板內也可以再定義成員函式的樣板。

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


    6982544

    本章習題


  • Login