C++之函數模板的概念和意義

2021-01-07 OFweek維科網

一、函數模板的引出:

1、c++中有幾種交換變量的方法:

(1)定義宏代碼塊

(2)定義函數

代碼版本一:

#include <iostream>
#include <string>
using namespace std;
#define SWAP(t,a,b)  
do                    
{                    
    t c =a;          
    a =b;            
    b = c;          
}while(0)
int main()

    int a =2;
    int b =5;
    SWAP(int , a , b );
    cout<<"a= "<<a<<endl;
    cout<<"b= "<<b<<endl;
    double m =4;
    double n =6;
    cout<<"m = "<<m<<endl;
    cout<<"n= "<<n<<endl;
    return 0;

輸出結果:

root@txp-virtual-machine:/home/txp# ./a.out
a= 5
b= 2
m = 4
n= 6

註解:我們看兩個數值交換成功。

我們再用使用函數的方式來實現這個功能,當然以前我們在c語言裡面使用指針傳參方式來實現這種兩個數值直接的交換,現在我們利用c++裡面更加高級的方式來實現,就是使用引用來實現(不過它的本質還是指針來實現,只是我們只用引用再不用去考慮指針的細節了)

代碼版本二:

#include <iostream>
#include <string>
using namespace std;
void Swap(int& a , int& b )//const int * a ,const int * b '

   int c =a;
   a=b;
   b=c;

void Swap(double& a,double& b)

   double c =a;
   a=b;
   b=c;

void Swap( string& a, string& b)

   string c =a;
   a=b;
   b=c;

int main()

 int a =2;
 int b =5;
 Swap(a,b);
 cout<<"a= "<<a<<endl;
 cout<<"b= "<<b<<endl;
 double m =4;
 double n =6;
 cout<<"m= "<<m<<endl;
 cout<<"n= "<<n<<endl;
 string d = "Txp";
 string t = "xiaoping";
 cout<<"d= "<<d<<endl;
 cout<<"t= "<<t<<endl;
 return 0;

輸出結果:

root@txp-virtual-machine:/home/txp# ./a.out
a= 5
b= 2
m= 4
n= 6
d= Txp
t= xiaoping

註解:同樣實現了交換功能。

2、兩種方法的優缺點:

定義宏代碼塊

-優點:代碼復用,適合所有的類型

-缺點:編譯器不知道宏的存在,缺少類型檢查

定義函數

-優點:真正的函數調用,編譯器對類型進行檢查

-缺點:根據類型重複定義函數,無法diam復用,從上面的試驗結果可以看出,我們每次都對Swap()函數進行重新定義,定參數的類型不一致的時候

二、泛型編程閃亮出場:

1、泛型編程的概念:

不考慮具體數據類型的編程方式,我們可以繼續拿我們剛才的那個Swap函數進行改造,改成我們現在的泛型寫過:

void Swap(T& a, T& b)

    T t =a;
    a =b;
    b =t;

註解:Swap泛型寫法中的T不是一個具體的數據類型,而是泛指任意的數據類型,這一點非常重要,明顯有了很大提升。

2、C++中泛型編程

(1)函數模板:

-一種特殊的函數可用不同類型進行調用

-看起來和普通函數很相似,區別是類型可以被參數化

template<typename T>
void Swap(T& a, T& b)

  T t = a;
  a = b;
  b = t;

(2)函數模板的語法規則:

template關鍵字用於聲明開始進行泛型編程

template關鍵字用於聲明泛指類型

(3)函數模板的使用

自動類型推導調用

具體類型顯示調用

int a = 0;
int b =1;
Swap(a,b)//這裡屬於自動推導
float c =2;
float d =6;
Swap<float>(c,d);//這裡屬於顯示調用

代碼實踐:

#include <iostream>
#include <string>
using namespace std;
template < typename T >// 開始泛型編程,泛指類型是 T;在下面函數定義中用 T 可以代表類型;
void Swap(T& a, T& b)

   T c =a;
   a=b;
   b=c;

template < typename T >
void Sort(T a[], int len)

  for(int i=0;i<len;i++)
  {
     for(int j=i;j<len;j++)
     {
        if(a[i] > a[j])
        {
            Swap(a[i],a[j]);
        }
     }
  }

template < typename T >
void Println(T a[], int len)

     for(int i=0;i<len;i++)
     {
          cout<<a[i]<<",";
     }
     cout<<endl;

int main()

 int a=3;
  int b=5;
  Swap(a,b);//自動推導,等價於 Swap<int>(a, b);
  cout<<"a= "<<a<<endl;
  cout<<"b= "<<b<<endl;
  double m =4;
  double n=6;
  Swap(m,n);
  cout<<"m= "<<m<<endl;
  cout<<"n= "<<n<<endl;
  string d = "Txp";
  string t ="xiaoping";
  Swap<string>(d,t);//顯示指定;將 T 替換成 string,然後進行調用;
  cout<<"d= "<<d<<endl;
  cout<<"t= "<<t<<endl;
     以下是選擇排序算法測試代碼
  int array[5]={3,5,6,4,9};
  Println(array,5);
  Sort(array,5);
  Println(array,5);
  string s[5]={"c","c++","rust","golang","python"};
  Println(s,5);
  Sort(s,5);
  Println(s,5);
  return 0;

輸出結果:

vroot@txp-virtual-machine:/home/txp# ./a.out
a= 5
b= 3
m= 6
n= 4
d= xiaoping
t= Txp
3,5,6,4,9,
3,4,5,6,9,
c,c++,rust,golang,python,
c,c++,golang,python,rust,

三、總結:

函數模板是泛型編程在c++中的應用方式之一

函數模板能夠根據實參對參數類型進行推導

函數模板支持顯示的指定參數類型

函數模板是C++中重要的代碼復用方式

好了,今天的分享就到這裡,如果文章中有錯誤或者不理解的地方,可以交流互動,一起進步。我是txp,下期見!

相關焦點

  • c++之重載函數學習總結
    當函數名和不同的參數搭配時函數的含義不同注意:在c語言中是沒有函數重載這個概念的。6、小結:函數重載是c++中引入的概念函數重載的本質是相互獨立的不同函數c++中通過函數名和函數參數確定函數調用二、重載函數進階學習1、重載與指針:下面的函數指針將保存哪個函數的地址?
  • C++類與回調函數
    在C++中的一個重要概念就是類,所以我們一般想讓類的成員函數作為回調函數(如果直接用非類的成員函數作為回調函數,其實就和C語言中的方法一樣),但是想實現這樣的功能,還是存在一些限制的。,分析下原因,其實是B::CB的函數是非靜態成員函數,它隱藏了this參數,導致p_CB和B::CB這兩個函數的參數不匹配。
  • C++中多態的概念和意義
    ;而不是根據指針類型(編譯器默認的安全行為);父類指針(引用)指向:父類對象,則調用父類中定義的函數;子類對象,則調用子類中定義的重寫函數;      3、面向對象中的多態的概念:   4、C++ 語言直接支持多態的概念:
  • C++typename的由來和用法
    本文轉載自【微信公眾號:羽林君,ID:Conscience_Remains】經微信公眾號授權轉載,如需轉載與原文作者聯繫前言在C++模板函數的使用過程中,我們經常可以看到一個typename的使用,例如這樣的操作但是除此之外
  • 跟我學C++中級篇——STL的學習
    一、c++標準庫C++的標準庫主要包含兩大類,首先是包含C的標準庫的,當然,為了適應c++對一些C庫進行了少許的修改和增加。最重要的當然是面向對象的c++庫;而c++庫又可以分成兩大類,即面向對象的c++庫和標準模板庫,也就是題目中的STL。
  • C++模板之SFINAE和enable_if分析
    ,感興趣的同學一起和小編學習吧。SFINAESFINAE是"Substitution failure is not an error"(替換失敗不是錯誤),官方給的解釋為:在函數模板的重載決議中:為模板形參替換推導類型失敗時,從重載集拋棄特化,而非導致編譯錯誤。用一句簡單的話來說,C++在編譯的時候,模板實例化的時候就算實例化失敗也不會出現錯誤。
  • 高中數學《函數的概念》教學設計及說課稿模板!
    教師之夢微信公眾號在之前也發過不少教學設計模板和一些萬能模板,需要的同學可以在後臺回復教學設計進行查看。預設:函數的概念:給定兩個非空數集A和B,如按照某個對應關係f,對於集合A中任何一個數x,在集合B中都存在唯一確定的數f(x)與之對應,那麼就把這對應關係f佳作定義在集合A上的函數,記作f:A→B,或y=f(x),x∈A。此時,x叫做自變量,幾何A叫做函數的定義域,幾何{f(x)▏x∈A }叫做函數的值域。函數的三要素包括:定義域、值域、對應法則。
  • C++、java 和 C 的區別
    的區分 ,這個跟java和c# 的區別比較大,但c#裡面有unit ulong ushort 這三種就相當於c++的修飾詞unsigned,當c++李明的變量類型定義unsigned,就默認是整數。2.java和c#裡面都有字符串型 和byte型, 但c++裡面沒有,但它是以另外的形式存儲這類型的數據的,比如 java和c#裡面的 byte其實就是unsigned char類型;c++中字符數組就能存儲字符串 (char a[]={"hello"}; ps:注意c++裡面定義數組 變量必須在中括號前面)。
  • c++11新特性,所有知識點都在這了!
    完美轉發:可以寫一個接受任意實參的函數模板,並轉發到其它函數,目標函數會收到與轉發函數完全相同的實參。+11新增了std::function、std::bind、lambda表達式等封裝使函數調用更加方便,詳細介紹請看:搞定c++11新特性std::function和lambda表達式模板的改進C++11關於模板有一些細節的改進:詳細介紹請看:C++11
  • 深入了解C++(6):auto與函數模板之推導規則辨析
    再探值與引用】一文中函數模板中的參數推導規則一致。「值傳遞」在auto不加上任何修飾符以及引用時,推導變量類型,其推導規則和基於值傳遞的函數模板推導規則一致:demo演示如下:  int「by the way」但是當auto用於推導函數參數的類型時,就和函數模板一樣,也無法識別{...}。
  • C++語言虛函數實現多態的原理
    自上一個帖子之間跳過了一篇總結性的帖子,之後再發,今天主要研究了c++語言當中虛函數對多態的實現,感嘆於c++設計者的精妙絕倫C++中虛函數表的作用主要是實現了多態的機制。首先先解釋一下多態的概念,多態是C++的特點之一,關於多態,簡而言之就是 用父類的指針指向其子類的實例,然後通過父類的指針調用實際子類的成員函數。
  • C++基礎總結(一):從「hello world」入門C++!
    面向對象程序設計c++最大的亮點就是面向對象程序設計理念的運用。包括面向對象開發的四大特性:封裝;抽象;繼承;多態C++的組成部分標準的 C++ 由三個重要部分組成:核心語言,提供了所有構件塊,包括變量、數據類型和常量,等等。
  • 現代C++函數式編程之function compose
    Composing function calls假設我們有兩個函數f和g,組合f,g意味著f(g(x)), 即先計算函數
  • C++模板進階指南:SFINAE
    這一句之乎者也般難懂的話,由之乎者 —— 啊,不,Substitution,Failure和Error三個詞構成。我們從最簡單的詞「Error」開始理解。Error就是一般意義上的編譯錯誤。一旦出現編譯錯誤,大家都知道,編譯器就會中止編譯,並且停止接下來的代碼生成和連結等後續活動。其次,我們再說「Failure」。
  • C++模板的介紹
    模板是泛型編程的基礎,泛型編程即以一種獨立於任何特定類型的方式編寫代碼。C++模板的作用,類似於C中的typedef,不過C++中模板有更多的靈活性。C++模板類型,類似於Objective-C中的泛型。C++通過類模板來實現泛型支持。2.C++中有兩種模板,分別是函數模板和類模板。
  • C/C++可變參數函數
    但在某些情況下希望函數的參數個數可以根據需要確定,因此c語言引入可變參數函數。這也是c功能強大的一個方面,其它某些語言,比如fortran就沒有這個功能。典型的可變參數函數的例子有大家熟悉的printf()、scanf()等。二、c/c++如何實現可變參數的函數?
  • C++ | 虛函數簡介
    本文將簡單探究一下 c++ 中的虛函數實現機制。本文主要基於 vs2013 生成的 32 位代碼進行研究,相信其它編譯器(比如,gcc)的實現大同小異。先從對象大小開始 假設我們有如下代碼,假設 int 佔 4 字節,指針佔 4 字節。
  • 新手入門:關於C++中的內聯函數(inline)
    >   在c++中,為了解決一些頻繁調用的小函數大量消耗棧空間或者是叫棧內存的問題,特別的引入了inline修飾符,表示為內聯函數。奇":"偶";    }  上面的例子就是標準的內聯函數的用法,使用inline修飾帶來的好處我們表面看不出來,其實在內部的工作就是在每個for循環的內部所有調用dbtest(i)的地方都換成了(i%2>0)?"奇":"偶"這樣就避免了頻繁調用函數對棧內存重複開闢所帶來的消耗。
  • python3使用ctypes在windows中訪問C和C++動態連結庫函數示例
    python3使用ctypes在windows中訪問C和C++動態連結庫函數示例這是我們的第一個示例,我們儘量簡單,不傳參,不返回,不訪問其他的動態連結庫一 測試環境介紹和準備c語言函數,如果你源碼是.c也就是用c語言編譯則不需要加extern "C"。
  • C++ 優先隊列priority_queue
    只有排好了隊伍才會有落後和優先之分,否則一團亂糟糟的,怎麼才能分出優先的,所以優先隊列一定應用了排序。可是排序要怎樣實現呢?其實排序這個底層邏輯你是不用管的,你只要把想要的數據放到優先隊列裡,然後取出的必定是當前狀態下最優的,當然,究竟什麼是最優的條件是需要你來設定的,也就是說我們需要定義排序的規則。