初識c++中的函數模板

函數模板

函數模板概念

函數模板:編譯器生成代碼的一個規則。函數模板代表了一個函數家族,該函數模板與類型無關,在使用時被參數化,根據實參類型產生函數的特定類型版本。

函數模板格式

//要讓這個函數與類型無關
//Add函數模板
template<class T,typename s>	//模板的參數列表
//告訴編譯器T是一種類型
T Add(T left, T right)
{return left + right;
}

函數模板原理

針對于下面的代碼,我們看編譯器給我們的反匯編代碼,來了解函數模板編譯器是怎么處理的?

T Add(T left, T right)
{cout << typeid(T).name() << endl;return left + right;
}
int main()
{//對函數模板實例化Add(1, 2);Add(1.0, 2.0);Add('1', '2');return 0;
}

在這里插入圖片描述
每個函數地址不一樣,說明編譯器為每個類型都準備了相對應的函數
在編譯階段,如果編譯器檢測到對某個函數模板實例化

  1. 對實參類型進行推演(和函數重載有點像),根據推演的結果,確認模板參數列表中T的實際類型
  2. 將它集合函數模板,處理具體類型的函數,生成對應類型的函數

但是下面這個調用,就會報錯,因為第一參數給成整型,編譯器就會認為T是整型,但是第二個參數是double類型,那么編譯器又認為T是double類型,兩者沖突,編譯器就不知道T到底是什么。
模板一般不會進行相應類型轉化

Add(1,2.0)

解決方法:

T Add(T left, T2 right)
{cout << typeid(T).name() << endl;return left + right;
}

也可以手動進行強制類型轉換
也可以這樣調用Add<int>('1', '2.0');

函數模板的實例化

用不同類型的參數使用函數模板時,稱為函數模板的實例化。模板參數實例化分為:隱式實例化和顯示實例化

隱式實例化

讓編譯器根據實參推演模板參數的實際類型

T Add(T left, T right)
{cout << typeid(T).name() << endl;return left + right;
}
int main()
{//對函數模板實例化Add(1, 2);Add(1.0, 2.0);Add('1', '2');return 0;
}
顯示實例化

在函數名后的<>中指定模板參數的實際類型
如果類型不匹配,編譯器會嘗試進行隱式類型轉換,如果無法轉換成功編譯器將會報錯。

Add<int>('1', '2.0');

函數模板參數的匹配原則

  1. 一個非模板函數可以和一個同名的函數模板同時存在,而且該函數模板還可以被實例化為這個非模板函數
int Add(int left, int right)
{return right + left;
}
template<class T>
T Add(T left, T right)
{return left + right;
}int main()
{//同名函數與函數模板同時存在時,優先使用模板生成的函數Add<>(1, 2); //隱式實例化Add(1,2);return 0;
}
  1. 對于非模板函數和同名函數模板,如果其他條件都相同,在調動時會優先調用非模板函數而不會從該模板產生出一個實例。如果模板可以產生一個具有更好匹配的函數, 那么將選擇模板
int Add(int left, int right)
{return right + left;
}
template<class T>
T Add(T left, T right)
{return left + right;
}
int main()Add(1, 2); // 與非函數模板類型完全匹配,不需要函數模板實例化Add(1, 2.0); // 模板函數可以生成更加匹配的版本,編譯器根據實參生成更加匹配的Add函數return 0;
}
  1. 模板函數不允許自動類型轉換,但普通函數可以進行自動類型轉換

類模板

類模板的定義

typedef int DataType;
template<class T>
class SeqList
{
public:SeqList(size_t capacity = 10):_array(new T(capacity)), _size(0), _capacity(capacity){}~SeqList(){delete[] _array;_array = nullptr;_capacity = 0;_size = 0;}//尾部void PushBack(const T& data);void PopBack(){--_size;}//任意位置插入和刪除/*void Insert(size_t pos, T&data);void Erase(size_t pos);*///在const類型成員函數中不能修改成員變量//const修飾this指針size_t size()const{return _size;}size_t Capacity()const{return _capacity;}bool Empty()const{return 0 == _size;}T&operator[](size_t index){assert(index < _size);return _array[index];}const T&operator[](size_t index) const{assert(index < _size);return _array[index];}
private:void _CheckCapacity(){if (_size == _capacity){//開辟新空間T* array = new T[2 * _capacity];//拷貝元素//memcpy(array, this->_array, _size*sizeof(T));for (size_t i = 0; i < _size; ++i){array[i] = _array[i];}//釋放舊空間delete[] _array;_array = array;_capacity *= 2;}}
private:T* _array;size_t _size;size_t _capacity;
};
template<class T>
void  SeqList<T>::PushBack(const T& data)
{_CheckCapacity();_array[_size] = data;_size++;
}

類模板的實例化

類模板實例化與函數模板實例化不同,類模板實例化需要在類模板名字后跟<>,然后將實例化的類型放在<>中即可,類模板名字不是真正的類,而實例化的結果才是真正的類。

void TestSeqList()
{SeqList<int> s1;s1.PushBack(1);s1.PushBack(2);s1.PushBack(3);s1.PushBack(4);cout << s1[2] << endl;s1[2] = 10;cout << s1.size() << endl;cout << s1.Capacity() << endl;cout << s1[2] << endl;SeqList<double> s2;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383134.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383134.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383134.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

深入理解c++中的函數模板

非類型模板參數 模板參數分類類型形參與非類型形參。 類型形參&#xff1a;出現在模板參數列表中&#xff0c;跟在class或者typename之類的參數類型名稱。 非類型形參&#xff0c;就是用一個常量作為類(函數)模板的一個參數&#xff0c;在類(函數)模板中可將該參數當成常量來使…

c++中的IO流

c語言中的IO操作 標準類型的輸入輸出: 輸入------>數據來源是通過鍵盤進行輸入輸出------>程序中的數據輸出到控制臺 c語言中: scanf:輸入 printf:輸出 兩個函數的相同點 1 —格式串 2 —不定參數 兩個函數的缺陷 1 —用戶要提供數據的格式—用戶要記憶大量的格式串—…

201301 JAVA2~3級---走格子

請編寫一個函數&#xff08;允許增加子函數&#xff09;&#xff0c;計算n x m的棋盤格子&#xff08;n為橫向的格子數&#xff0c;m為豎向的格子數&#xff09;沿著各自邊緣線從左上角走到右下角&#xff0c;總共有多少種走法&#xff0c;要求不能走回頭路&#xff0c;即&…

復習Linux基本操作----常見指令

Linux基本操作 ls命令 ls(list):相當于windows上的文件資源管理器 語法&#xff1a; ls [選項][目錄或文件] 功能&#xff1a;對于目錄&#xff0c;該命令列出該目錄下的所有子目錄與文件。對于文件&#xff0c;將列出文件名以及其他信息。 常用選項&#xff1a; -a 列出目…

復習Linux基礎操作---權限操作

shell命令以及運行原理 Linux嚴格意義上說的是一個操作系統&#xff0c;我們稱之為“核心&#xff08;kernel&#xff09;“ &#xff0c;但我們一般用戶&#xff0c;不能直接使用kernel。而是通過kernel的“外殼”程序&#xff0c;也就是所謂的shell&#xff0c;來與kernel溝…

【劍指offer】_01 (二維數組中的查找)

題目描述 在一個二維數組中&#xff08;每個一維數組的長度相同&#xff09;&#xff0c;每一行都按照從左到右遞增的順序排序&#xff0c;每一列都按照從上到下遞增的順序排序。請完成一個函數&#xff0c;輸入這樣的一個二維數組和一個整數&#xff0c;判斷數組中是否含有該…

【劍指offer】_02替換空格

題目描述 請實現一個函數&#xff0c;將一個字符串中的每個空格替換成“%20”。例如&#xff0c;當字符串為We Are Happy.則經過替換之后的字符串為We%20Are%20Happy。 解題思路 首先我們先算出整個字符串的長度&#xff0c;還有總共多少個空格。因為空格只占一個字節&#…

【劍指offer】_04 重建二叉樹

題目描述 輸入某二叉樹的前序遍歷和中序遍歷的結果&#xff0c;請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重復的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6}&#xff0c;則重建二叉樹并返回。 解題思路 用前序的順序…

再談c++中的多態

何為多態 多態的概念&#xff1a;通俗來說&#xff0c;就是多種形態&#xff0c;具體點就是去完成某個行為&#xff0c;當不同的對象去完成時會產生出不同的狀態。 多態的實現 在繼承的體系下 基類中必須有虛函數(被virtual關鍵字修飾的成員函數)&#xff0c;在派生類中必須…

再談c++中的繼承

繼承的概念 繼承(inheritance)機制是面向對象程序設計使代碼可以復用的最重要的手段&#xff0c;它允許程序員在保持原有類特性的基礎上進行擴展&#xff0c;增加功能&#xff0c;這樣產生新的類&#xff0c;稱派生類。繼承呈現了面向對象程序設計的層次結構&#xff0c;體現了…

紅黑樹概念及其相關操作的實現

紅黑樹的概念 紅黑樹&#xff0c;是一種二叉搜索樹&#xff0c;但它并不像AVL樹一樣&#xff0c;每個結點綁定一個平衡因子。但在每個結點上增加一個存儲位表示結點的顏色&#xff0c;可以是Red或Black。 通過 對任何一條從根到葉子的路徑上各個結點著色方式的限制&#xff0c…

模擬實現STL中map和set容器

紅黑樹的迭代器 //紅黑樹的迭代器 template<class T> struct RBTreeIterator {typedef RBTreeNode<T>Node;typedef RBTreeIterator<T> Self; public:RBTreeIterator(Node* pNode nullptr):_pNode(pNode){}//具有指針操作T& operator*(){return _pNode-…

【劍指offer】_05 連續子數組最大和

題目描述 HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會后,他又發話了:在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數,并期望旁邊的正數會彌補它呢&#…

排序上---(排序概念,常見排序算法,直接插入,希爾排序,直接選擇排序,堆排序)

排序的概念 排序&#xff1a;所謂排序&#xff0c;就是使一串記錄&#xff0c;按照其中的某個或某些關鍵字的大小&#xff0c;遞增或遞減的排列起來的操作。穩定性&#xff1a;假定在待排序的記錄序列中&#xff0c;存在多個具有相同的關鍵字的記錄&#xff0c;若經過排序&…

排序下---(冒泡排序,快速排序,快速排序優化,快速排序非遞歸,歸并排序,計數排序)

排序上 排序上 交換類排序 基本思想&#xff1a;所謂交換&#xff0c;就是根據序列中兩個記錄鍵值的比較結果來對換這兩個記錄在序列中的位置&#xff0c;交換排序的特點是&#xff1a;將鍵值較大的記錄向序列的尾部移動&#xff0c;鍵值較小的記錄向序列的前部移動。 冒泡…

哈希的概念及其操作

哈希概念 順序結構以及平衡樹中&#xff0c;元素關鍵碼與其存儲位置之間沒有對應的關系&#xff0c;因此在查找一個元素時&#xff0c;必須要經過關鍵碼的多次比較。順序查找時間復雜度為O(N)&#xff0c;平衡樹中為樹的高度&#xff0c;即O( Log2N)&#xff0c;搜索的效率取決…

軟件工程---1.概述

軟件的特征 抽象&#xff1a; 不可觸摸&#xff0c;邏輯實體&#xff0c;可記錄&#xff0c;但看不到復制成本低&#xff1a;不受物質材料的限制&#xff0c;不受物理定律或加工過程的制約&#xff0c;與開發成本相比&#xff0c;復制成本很低無折舊、受硬件制約、未完全擺脫手…

軟件工程---2.軟件過程

三個模型 瀑布模型增量模型集成和配置模型 沒有適用于所有不同類型軟件開發的過程模型。 瀑布模型 需求定義系統和軟件的設計實現與單元測試集成與系統測試運行與維護 瀑布模型的特征 從上一項活動中接受該項活動的工作成果&#xff08;工作產品&#xff09;&#xff0c;作…

軟件工程---3.敏捷軟件開發

敏捷軟件開發 極限編程&#xff08;XP&#xff0c; Beck1999&#xff09;Scrum方法&#xff08;Schwaber and Beedle 2001&#xff09;DSDM方法&#xff08;Stapleton 2003&#xff09; 敏捷軟件的開發宣言 個體和交互勝過過程和工具可以工作的軟件勝過面面俱到的文檔客戶合…

軟件工程---4.需求工程

需求工程定義 找出、分析、文檔化并且檢查需求的過程被稱為需求工程 需求的兩個描述層次 用戶需求&#xff0c;指高層的抽象需求。使用自然語言、圖形描述需求。系統需求&#xff0c;指底層的詳細需求。使用系統需求文檔&#xff08;有時被稱為功能規格說明&#xff09;應該…