函式模板

TuxedoLinux發表於2018-05-26

函式模板
函式模板能夠用來建立一個通用的函式。以支援多種不同的形參。避免過載函式的函式體反覆設計。

它的最大特點是把函式使用的資料型別作為引數。


函式模板的宣告形式為:

template<typename(或class) T>
<返回型別><函式名>(參數列)
{
    函式體
}

當中,template是定義模板函式的關鍵字;template後面的尖括號不能省略;typename(或class)是宣告資料型別引數識別符號的關鍵字。用以說明它後面的識別符號是資料型別識別符號。這樣,在以後定義的這個函式中,凡希望依據實引數據型別來確定資料型別的變數,都能夠用資料型別引數識別符號來說明,從而使這個變數能夠適應不同的資料型別。

比如:

template<typename(或class) T>
T fuc(T x, T y)
{
    T x;
    //……
}

函式模板僅僅是宣告瞭一個函式的描寫敘述即模板。不是一個能夠直接執行的函式,僅僅有依據實際情況用實參的資料型別取代型別引數識別符號之後,才幹產生真正的函式。

 

C++中的模板template

 

    這個是C++中的模板..template<typename T> 這個是定義模板的固定格式,規定了的..模板應該可以理解到它的意思吧.. 比如你想求2個int float 或double型變數的值,只需要定義這麼一個函式就可以了,假如不用模板的話,你就必須針對每種型別都定義一個sum函式..int sum(int, int);float sum(float, float);double sum(double, double);

 

1.因為T是一個模版例項化時才知道的型別,所以編譯器更對T不知所云,為了通知編譯器T是一個合法的型別,使用typename語句可以避免編譯器報錯。 
2.template < typename var_name > class class_name; 表示var_name是一個型別, 在模版例項化時可以替換任意型別,不僅包括內建型別(int等),也包括自定義型別class。 換句話說,在template<typename Y>和template<class Y>中, 
typename和class的意義完全一樣。 
建議在這種語句中儘可能採用typename,以避免錯覺(因為只能替換class,不能只換int), 
這也是C++新標準引進typename關鍵詞的一個初衷

 

   下面我們以求兩個數中的最大值為例介紹Template(模板)的使用方法。

 


 
  1. <pre name="code" class="cpp">// TemplateTest.cpp : 定義控制檯應用程式的入口點。

  2. ///<summary>

  3. ///測試C++中的template(模板)的使用方法 最新整理時間2016.5.21

  4. ///</summary>

  5. ///<remarks>1:template的使用是為了簡化不同型別的函式和類的重複定義.

  6. ///<remarks>2:char型別變數c,d輸入的都是字母,不是數字,如輸入32則c=3,d=2.

  7. #include "stdafx.h"

  8. #include <iostream>

  9. #include<vector>

  10. using namespace std;

  11. template <typename T>

  12. T mmax(T a,T b)

  13. {

  14. return a>b?a:b;

  15. }

  16. int _tmain(int argc, _TCHAR* argv[])

  17. {

  18. cout<<"Please enter the value of a and b:"<<endl;

  19. int a,b;

  20. cin>>a>>b;

  21. cout<<mmax(a,b)<<endl;

  22. cout<<"Please enter the value of c and d:"<<endl;

  23. char c,d;

  24. cin>>c>>d;

  25. cout<<mmax(c,d)<<endl;

  26. cout<<"Please enter the value of f and g:"<<endl;

  27. double f,g;

  28. cin>>f>>g;

  29. cout<<mmax(f,g)<<endl;

  30. while(1);

  31. return 0;

  32. }

C++模板(關鍵字template,typename)介紹

C++模板

  模板是C++支援引數化多型的工具,使用模板可以使使用者為類或者函式宣告一種一般模式,使得類中的某些資料成員或者成員函式的引數、返回值取得任意型別。

  模板是一種對型別進行引數化的工具;

  通常有兩種形式:函式模板類别範本

  函式模板針對僅引數型別不同的函式

  類别範本針對僅資料成員成員函式型別不同的類。

  使用模板的目的就是能夠讓程式設計師編寫與型別無關的程式碼。比如編寫了一個交換兩個整型int 型別的swap函式,這個函式就只能實現int 型,對double,字元這些型別無法實現,要實現這些型別的交換就要重新編寫另一個swap函式。使用模板的目的就是要讓這程式的實現與型別無關,比如一個swap模板函式,即可以實現int 型,又可以實現double型的交換。模板可以應用於函式和類。下面分別介紹。

  注意:模板的宣告或定義只能在全域性,名稱空間或類範圍內進行。即不能在區域性範圍,函式內進行,比如不能在main函式中宣告或定義一個模板。

 

 一、函式模板通式


1、函式模板的格式:

    template <class 形參名,class 形參名,......> 返回型別 函式名(引數列表)

   {

      函式體

   }

  其中templateclass是關見字,class可以用typename 關見字代替,在這裡typename 和class沒區別,<>括號中的引數叫模板形參,模板形參和函式形參很相像,模板形參不能為空。一但宣告瞭模板函式就可以用模板函式的形參名宣告類中的成員變數和成員函式,即可以在該函式中使用內建型別的地方都可以使用模板形參名。模板形參需要呼叫該模板函式時提供的模板實參來初始化模板形參,一旦編譯器確定了實際的模板實參型別就稱他例項化了函式模板的一個例項。比如swap的模板函式形式為

      template <class T> void swap(T& a, T& b){},

當呼叫這樣的模板函式時型別T就會被被呼叫時的型別所代替,比如swap(a,b)其中abint 型,這時模板函式swap中的形參T就會被int 所代替,模板函式就變為swap(int &a, int &b)。而當swap(c,d)其中cddouble型別時,模板函式會被替換為swap(double &a, double &b),這樣就實現了函式的實現與型別無關的程式碼。

  2、注意:對於函式模板而言不存在 h(int,int) 這樣的呼叫,不能在函式呼叫的引數中指定模板形參的型別,對函式模板的呼叫應使用實參推演來進行,即只能進行 h(2,3) 這樣的呼叫,或者int a, b; h(a,b)

 

C++函式模板

2018年06月29日 13:28:44 jigetage 閱讀數:453

原文地址:點選開啟連結

 

前言

有些人提到C++模板就會下意識地覺得可怕、看不懂、避而遠之。其實模板並不複雜,而且熟練後可以用在日常工作中,可以幫助我們重用程式碼,讓程式碼更簡潔、易讀、可維護。希望這個系列的文章,能夠讓更多人發現模板的魅力,幫助大家寫出更高質量的程式碼。

我們為什麼需要模板

我們有時候會遇到這樣的情況:同樣的函式,我們要為不同的型別寫不同的版本,內容與邏輯都是一摸一樣的,只有他們的型別不一樣。比如我們寫一個max函式,傳入兩個數字,返回大的數字。很自然地,兩個引數的型別和返回的型別必須是相同的。如果不使用模板,我們需要使用函式過載,為不同的型別寫不同的函式:

複製程式碼

int max(int a, int b)
{
     return a < b ? b : a;
}

float max(float a, float b)
{
     return a < b ? b : a;
}

複製程式碼

這裡我只寫了2個函式,實際上short, long, unsigned, double等等型別都需要專門的max函式,結果就是需要寫十幾個幾乎一摸一樣的程式碼。如果函式功能更復雜一些,函式實現需要更多行,就會出現大量冗餘重複的程式碼,而且不容易維護,很容易出錯。這個時候如果我們能夠根據特定的模板批量生成一系列程式碼,將會方便很多。為此,我們可以使用C++中的模板

什麼是模板

顧名思義,模板就是編譯器生成程式碼用的模子。模板有兩類,函式模板和類别範本(C++14開始出現了變數模板,不過不在此討論)。如果想要生成函式程式碼,則需要用函式模板,如果想要生成類定義,則需要用到類别範本。這篇文章會先介紹函式模板,下篇文章再介紹類别範本。

函式模板

我們可以為上面的一系列max函式寫一個函式模板。

template<typename T>
T max(T a, T b)
{
     return a < b ? b : a;
}

我們暫時不細說語法,先看一看大致的樣子,其實函式模板的長相和普通的函式是很像的。

好了,我們已經定義了一個函式模板,那麼怎麼去生成函式程式碼?事實上我們不需要做額外的事情,如果我們使用了max函式,編譯器就會自動幫我們生成對應型別的程式碼。函式模板的使用方式很簡單,只需要在模板的名字後面寫一對尖括號,尖括號內寫上實參列表就可以使用了。

double d = max<double>(1.2, 2.4);

編譯器看到這一行,就會自動幫我們生成double版本的max函式,生成出來的函式等價於把函式模板中的所有T都替換成double。在這裡max<double>可以看做是double版本的max函式的函式名,我們甚至還可以用&max<double>來獲取這個函式的地址。

我們來看一個更復雜的例子

複製程式碼

template<typename T, int i>
T create()
{
    T value();
    return value + i;
}

int main()
{
    float f1 = create<float, 1>();    // f1 == 1.0
    float f2 = create<float, 2>();    // f2 == 2.0
}

複製程式碼

這個例子裡面我們定義了一個create函式模板,根據模板建立並使用了兩個函式create<float, 1>和create<float, 2>。要注意的是,這兩個函式是不同的函式,有不同的函式體,和不同的函式地址。他們兩個分別等價於

複製程式碼

float create()    // create<float, 1>
{
    float value();
    return value + 1;
}

float create()    // create<float, 2>
{
    float value();
    return value + 2;
}

複製程式碼

我們總結一下函式模板的語法,模板定義由template關鍵字開始,後面跟著一對尖括號,尖括號裡面是模板形參列表,也就是模板的引數。模板形參列表的寫法和函式形參列表的寫法是很相似的。都是“型別 引數名, 型別 引數名, ...”這種形式。上面的例子中,模板形參列表就是“typename T, int i”。我們注意到,模板形參列表需要為每個形參指定一個型別,這個是因為形參不一定是C++型別,還可以是具體的值,例如數字,指標等等。如果形參是一個型別,則需要使用typename關鍵字來表示形參的型別,如果形參是一個值,則需要寫上這個值的型別。在使用模板的時候,要在模板的名字後面加一對尖括號,尖括號裡面是模板實參列表,在上面的例子中,實參列表就是“float, 1”和“float, 2”。與函式呼叫類似,使用模板的時候編譯器會檢查實參列表的型別與形參列表的型別是否匹配,不匹配的話會報錯。

使用函式模板的優點

我們可以從上面的例子中看出,用函式模板更方便簡潔,不需要重複寫類似的過載函式。除此外,因為函式程式碼是在使用的時候生成出來的,所以如果我們沒有使用這個函式,編譯器就不會生成這個程式碼,這樣我們可以減小程式的大小。例如,我們使用了max<double>,但是沒有使用max<int>,那麼程式中只有max<double>函式,不會有max<int>函式。

 

如何理解tcp的三次握手,四次揮手

 

  首先,我們要知道TCP是全雙工的,即客戶端在給伺服器端傳送資訊的同時,伺服器端也可以給客戶端傳送資訊。而半雙工的意思是A可以給B發,B也可以給A發,但是A在給B發的時候,B不能給A發,即不同時,為半雙工。 單工為只能A給B發,B不能給A發; 或者是隻能B給A發,不能A給B發。

  我們假設A和B是通訊的雙方。我理解的握手實際上就是通訊,發一次資訊就是進行一次握手

  • 第一次握手: A給B打電話說,你可以聽到我說話嗎?
  • 第二次握手: B收到了A的資訊,然後對A說: 我可以聽得到你說話啊,你能聽得到我說話嗎?  
  • 第三次握手: A收到了B的資訊,然後說可以的,我要給你發資訊啦!

  在三次握手之後,A和B都能確定這麼一件事: 我說的話,你能聽到; 你說的話,我也能聽到。 這樣,就可以開始正常通訊了。

 

  注意: HTTP是基於TCP協議的,所以每次都是客戶端傳送請求,伺服器應答,但是TCP還可以給其他應用層提供服務,即可能A、B在建立連結之後,誰都可能先開始通訊。

    

  如果兩次,那麼B無法確定B的資訊A是否能收到,所以如果B先說話,可能後面的A都收不到,會出現問題 。

  如果四次,那麼就造成了浪費,因為在三次結束之後,就已經可以保證A可以給B發資訊,A可以收到B的資訊; B可以給A發資訊,B可以收到A的資訊。

  


 

  那麼三次握手在正式情況下都做了什麼呢? 

第一次握手:

客戶端傳送一個TCP的SYN標誌位置1的包指明客戶打算連線的伺服器的埠,以及初始序號X,儲存在包頭的序列號(Sequence Number)欄位裡

 

 

 

第二次握手 :

伺服器發回確認包(ACK)應答。即SYN標誌位和ACK標誌位均為1同時,將確認序號(Acknowledgement Number)設定為客戶的I S N加1以.即X+1。

 

 

第三次握手

客戶端再次傳送確認包(ACK) SYN標誌位為0,ACK標誌位為1.並且把伺服器發來ACK的序號欄位+1,放在確定欄位中傳送給對方.並且在資料段放寫ISN的+1

 

 

即SYN就是詢問: 你能聽得到嗎?  ACK就是回到: 我能聽得到啊。 

 

 


 

TCP四次揮手的過程:

 

 

四次揮手:
A:“喂,我不說了 (FIN)。”A->FIN_WAIT1

B:“我知道了(ACK)。等下,上一句還沒說完。Balabala…..(傳輸資料)”B->CLOSE_WAIT | A->FIN_WAIT2

B:”好了,說完了,我也不說了(FIN)。”B->LAST_ACK

A:”我知道了(ACK)。”A->TIME_WAIT | B->CLOSED

A等待2MSL,保證B收到了訊息,否則重說一次”我知道了”,A->CLOSED

相關文章