C++——模板---函數模板---類模板

1、模板python

  • 模板的引入:
    • 模板的精神:類型參數化,即類型也是一種參數。
    • template所表明的泛型編程是C++語言中的重要組成部分。C++是一門強類型語言,沒法像動態語言(如python)那樣,編寫一段通用的邏輯,能夠把任意類型的變量傳進去。泛型編程彌補了這一點擺脫了類型的限制,提升了代碼的可重用性。
    • 模板是創建通用的與數據類型無關的算法的重要手段,可實現代碼重用。
  • 函數模板的定義與聲明:---函數模板實參推演
    • 定義:
      • template<模板參數表>返回值類型 函數名(函數形參表){......}//函數體
      • 模板參數主要是模板類型參數,尖括號中不能爲空。模板類型參數由typename(或class)+標識符構成。表示該標識符表明一種潛在的內置或用戶自定義數據類型。
    • 聲明:
      • 函數模板的聲明與函數聲明不一樣,函數模板的聲明必須含變量名。由於二者的編譯過程不同。函數模板必須先轉換成模板函數,再進行編譯。模板定義自己不參與編譯,而是編譯器模板的用戶使用模板時提供的類型參數生成代碼,再進行編譯。這一過程成爲模板的實例化。用戶提供不一樣的類型參數就會實例化出不一樣的代碼。
  • 類模板的定義與聲明:---類模板實例化
    • 定義:
      • template<模板參數表> class 類名 { //類定義體
        };//注意分號不可少
         templete<模板參數表>返回類型 類名<模板參數名錶>:: 成員函數名1(形參表) { ......;//成員函數定義體
        }

         模板參數表有兩種:模板類型參數和非模板類型參數。算法




 

2、函數模板---template關鍵字用於聲明開始進行泛型編程-----typename關鍵字用於聲明泛指類型----函數模板能夠自動推導類型進行調用,也能夠顯示指定具體類型進行調用。編程

  一、普通函數模板:數據結構

    •  1 template<typename T>
       2 int compare(const T& left,const T& right)  3 {  4 if(left<rigth)  5 {return -1;}  6 if(right<left)  7 {return 1;}
        reurn 0;
      8 } 9 10 compare<int>(1,2);//使用模板函數

  二、類的成員函數模板函數

不只普通函數能夠定義爲模板,類的成員函數也能夠定義爲模板spa

    • class printer { public: template<typename T>
      void print(const T& t) { cout<<t<<endl; } } printer p; p.print<const char*>("seu");//打印seu

  • 實參推斷:

爲了使用方便,除了直接爲函數模板指定類型參數外,還可讓編譯器從傳遞給函數的實參推斷參數類型,這一功能被稱爲模板實參推斷。指針

  • 實參推斷的使用:
    • 1 compare(1,2);//推斷T的類型爲int
      2 compare(1.0,2.0);//推斷T的類型爲double
      3 p.print("absdsaf");//推斷T的類型爲const char *
      4 
      5 int (*pf)(const int&,const int&)=compare;//推斷T的類型爲int; 6 //經過把函數模板賦值給一個指定類型的函數指針,讓編譯器根據這個指針的類型,對模板實參進行判斷

 

  三、函數模板的重載code

函數模板之間,函數模板與普通函數之間能夠重載。編譯器會根據調用時提供的函數參數,調用可以處理這一類型的最特殊的版本。在特殊性上,通常遵循以下順序:orm

  • 普通函數
  • 特殊函數(限制了T的形式的,指針,引用,容器等)
  • 普通模板(對T沒有任何限制的) 
  • 如何判斷哪一個模板函數更加特殊,原則是:若是模板B的全部實例均可以實例化模板A,而反過來不行,那麼B就比A特殊。即B的範圍大於A的範圍。
    •  1 template<typename T>
       2 void func(T& t) { //通用模板函數
       3     cout << "In generic version template " << t << endl;  4 }  5 
       6 template<typename T>
       7 void func(T* t) { //指針版本
       8     cout << "In pointer version template "<< *t << endl;  9 } 10 
      11 void func(string* s) { //普通函數
      12     cout << "In normal function " << *s << endl; 13 } 14 
      15 int i = 10; 16 func(i); //調用通用版本,其餘函數或者沒法實例化或者不匹配
      17 func(&i); //調用指針版本,通用版本雖然也能夠用,可是編譯器選擇最特殊的版本
      18 string s = "abc"; 19 func(&s); //調用普通函數,通用版本和特殊版本雖然也均可以用,可是編譯器選擇最特化的版本
      20 func<>(&s); //調用指針版本,經過<>告訴編譯器咱們須要用template而不是普通函數

  四、模板函數的特化blog

有時候函數模板並不能解決個別類型的問題,咱們必須對此進行定製,這就是函數模板的特化。函數模板的特化必須把全部的模板參數所有指定。

  • 1 template<>
    2 void func(int i) { 3     cout << "In special version for int "<< i << endl; 4 } 5 
    6 int i = 10; 7 func(i); //調用特化版本



 

 

3、類模板---

類模板只能顯示指定類型參數,沒法自動推斷參數類型。聲明的泛型類型參數能夠出如今類模板的任意地方。類模板必須在頭文件中實現,不能分開實如今不一樣的文件中。

類模板適合以相同的邏輯處理不一樣數據類型的數據,所以很是適合編寫數據結構相關的代碼。一般用來做爲容器(vector)或行爲(clonable)的封裝。

對於一個類模板printer,只能顯示的指定參數類型進行調用

  • printer<int> p(1);正確 printer p(1);錯誤
     
相關文章
相關標籤/搜索