C++面向?qū)ο蟪绦蛟O(shè)計(jì)(第4版)-課件 CH7_第1頁
C++面向?qū)ο蟪绦蛟O(shè)計(jì)(第4版)-課件 CH7_第2頁
C++面向?qū)ο蟪绦蛟O(shè)計(jì)(第4版)-課件 CH7_第3頁
C++面向?qū)ο蟪绦蛟O(shè)計(jì)(第4版)-課件 CH7_第4頁
C++面向?qū)ο蟪绦蛟O(shè)計(jì)(第4版)-課件 CH7_第5頁
已閱讀5頁,還剩155頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第7章運(yùn)算符重載本章主要教學(xué)內(nèi)容泛型程序設(shè)計(jì)的技術(shù)原理函數(shù)模板、類模板程序設(shè)計(jì)(包括內(nèi)聯(lián)函數(shù)模板、常量函數(shù)模板)模板參數(shù)(類型參數(shù)、非類型參數(shù)、默認(rèn)參數(shù))、模板實(shí)例化(函數(shù)模板實(shí)例化、類模板實(shí)例化、類成員函數(shù)實(shí)例化)模板重載和模板特化仿函數(shù)應(yīng)用、可變參數(shù)函數(shù)模板和元編程基礎(chǔ)STL程序設(shè)計(jì):函數(shù)對(duì)象,常用容器、迭代器和算法本章教學(xué)重點(diǎn)函數(shù)模板,類模板設(shè)計(jì)函板模板實(shí)例化、特化STL應(yīng)用:用list、vector、string、set、map、tuple等容器、迭代器和算法處理自定義類仿函數(shù)設(shè)計(jì)及應(yīng)用教學(xué)難點(diǎn)模板可變參數(shù)和元編程模板非類型參數(shù)元組程序設(shè)計(jì)第7章模板與STL模板(template)是C++實(shí)現(xiàn)代碼重用機(jī)制的重要工具,是泛型技術(shù)(即與數(shù)據(jù)類型無關(guān)的通用程序設(shè)計(jì)技術(shù))的基礎(chǔ)。模板是C++中相對(duì)較新的

語言機(jī)制,它實(shí)現(xiàn)了與具體數(shù)據(jù)類型無關(guān)的通用算法程序設(shè)計(jì),能夠提高軟件開發(fā)的效率,是程序代碼復(fù)用的強(qiáng)有力工具。本章主要介紹了函數(shù)模板和類模板兩類,以及STL庫中的幾個(gè)常用模板數(shù)據(jù)類型及其應(yīng)用。實(shí)現(xiàn)多態(tài)的方法是()將派生類對(duì)象賦給基類對(duì)象通過基類對(duì)象的指針調(diào)用派生類中虛函數(shù)版本通過基類的引用調(diào)用派生類虛函數(shù)版本通過派生類指針調(diào)用基類的虛函數(shù)版本ABCD提交投票最多可選2項(xiàng)7.1模板的概念1、有關(guān)模板的幾個(gè)重要概念(1)模板模板是對(duì)具有相同特性的函數(shù)或類的再抽象,模板是一種參數(shù)多態(tài)性的工具,可以為邏輯功能相同而類型不同的程序提供一種代碼共享的機(jī)制。一個(gè)模板并非一個(gè)實(shí)實(shí)在在的函數(shù)或類,僅僅是一個(gè)函數(shù)或類的描述,但它可以接受數(shù)據(jù)類型作為其調(diào)用參數(shù)并生成可用的函數(shù)或類,是參數(shù)化的函數(shù)和類,是創(chuàng)建函數(shù)或類的自動(dòng)化工具。(2)模板的類型函數(shù)模板類模板(3)抽象

模板從多個(gè)具有相同特性的同類事物推導(dǎo)出對(duì)該類事物共同特征的統(tǒng)一描述的過程。變量→類型對(duì)象→類類→類模板函數(shù)→函數(shù)模板(4)實(shí)例化

模板函數(shù)實(shí)例化是抽象的逆過程:由抽象類型定義具體變量的過程。模板實(shí)例化過程是:用實(shí)際數(shù)據(jù)類型代入模板每一種不同數(shù)據(jù)類型的實(shí)例化,都將生成一份不同的代碼7.1模板的概念動(dòng)物:有機(jī)物為食,是能夠自主運(yùn)動(dòng)或能夠活動(dòng)的有感覺的生物抽象Tmax(Ta,Tb)函數(shù)模板{returna>b?a:b;}intmin(inta,intb){return(a<b)?a:b;}floatmin(floata,floatb){return(a<b)?a:b;}doublemin(doublea,doubleb){return(a<b)?a:b;}抽象Tmax(Ta,Tb){returna>b?a:b;}實(shí)例化(5)模板的抽象與定義某些程序除了所處理的數(shù)據(jù)類型之外,程序代碼和功能完全相同,但為了實(shí)現(xiàn)它們,卻不得不編寫多個(gè)與具體數(shù)據(jù)類型緊密結(jié)合的程序。例如,為了求兩個(gè)int、float、double、char類型數(shù)中的最小數(shù),需要編寫下列函數(shù):intmin(inta,intb){return(a<b)?a:b;}floatmin(floata,floatb){return(a<b)?a:b;}doublemin(doublea,doubleb){return(a<b)?a:b;}charmin(chara,charb){return(a<b)?a:b;}…………有什么辦法只寫一次代碼,卻可以處理不同數(shù)據(jù)類型呢?7.1模板的概念C語言通過#define定義宏definemin(x,y)((x)<(y)?(x):(y))特點(diǎn):“自動(dòng)具備多態(tài)特征”不適合表達(dá)復(fù)雜的邏輯簡單的文本替代,不進(jìn)行任何語法檢查,不安全。C++方法一:函數(shù)重載缺點(diǎn):相同代碼,多次重復(fù)編寫!C++方法二:函數(shù)模板template<typenameT>Tmin(Ta,Tb){return(a<b)?a:b;}特點(diǎn):代碼復(fù)用的有效機(jī)制,可以根據(jù)類型生成相應(yīng)程序代碼。7.1模板的概念7.1模板的概念模板(函數(shù)模板或類模板)模板函數(shù)模板類對(duì)象實(shí)例化實(shí)例化實(shí)例化模板、模板函數(shù)、模板類和對(duì)象之間的關(guān)系7.2函數(shù)模板與模板函數(shù)1、函數(shù)模板的功能函數(shù)模板提供了一種通用的函數(shù)行為,該函數(shù)行為可以用多種不同的數(shù)據(jù)類型進(jìn)行調(diào)用,編譯器會(huì)據(jù)調(diào)用類型自動(dòng)將它實(shí)例化為具體數(shù)據(jù)類型的函數(shù)代碼,也就是說函數(shù)模板代表了一個(gè)函數(shù)家族。2、函數(shù)模板與函數(shù)重載的區(qū)別與普通函數(shù)相比,函數(shù)模板中某些函數(shù)元素的數(shù)據(jù)類型是未確定的,這些元素的類型將在使用時(shí)被參數(shù)化;與重載函數(shù)相比,函數(shù)模板不需要程序員重復(fù)編寫函數(shù)代碼,它可以自動(dòng)生成許多功能相同但參數(shù)和返回值類型不同的函數(shù)。

Tmin(Ta,Tb){return(a<b)?a:b;}T

Intmin(inta,intb){return(a<b)?a:b;}intint→T工廠:生產(chǎn)函數(shù)產(chǎn)品:函數(shù)原材料:類型1、函數(shù)模板的定義template

<typenameT1,typenameT2,…>返回類型函數(shù)名(參數(shù)表){

…… //函數(shù)模板定義體}template是定義模板的關(guān)鍵字;寫在一對(duì)<>中的T1,T2,…是模板參數(shù),其中的typename表示其后的參數(shù)可以是任意類型。模板參數(shù)常稱為類型參數(shù)或類屬參數(shù),在模板實(shí)例化(即調(diào)用模板函數(shù)時(shí))時(shí)需要傳遞的實(shí)參是一種數(shù)據(jù)類型,如int或double之類。函數(shù)模板的參數(shù)表中常常出現(xiàn)模板參數(shù),如T1,T27.2.1

函數(shù)模板的定義7.2.1

函數(shù)模板的定義【例7-1】求兩數(shù)最小值的函數(shù)模板。//Eg7-1.cpp#include<iostream>usingnamespacestd;template<classT>Tmin(Ta,Tb){ return(a<b)?a:b;}voidmain(){ doublea=2,b=3.4; floatc=2.3,d=3.2; cout<<"2,3的最小值是:"<<min(2,3)<<endl; cout<<"2,3.4的最小值是:"<<min(a,b)<<endl; cout<<"'a','b' 的最小值是:"<<min('a','b')<<endl; cout<<"2.3,3.2的最小值是:"<<min(c,d)<<endl;}程序運(yùn)行結(jié)果如下:2,3的最小值是:22,3.4的最小值是:2'a','b'的最小值是:a2.3,3.2的最小值是:2.37.2.1

函數(shù)模板的定義2、使用函數(shù)模板的注意事項(xiàng)①在定義模板時(shí),不允許template語句與函數(shù)模板定義之間有任何其他語句。template<typenameT>intx;

//錯(cuò)誤,不允許在此位置有任何語句Tmin(Ta,Tb){…}②函數(shù)模板可以有多個(gè)類型參數(shù),但每個(gè)類型參數(shù)都必須用關(guān)鍵字class或typename限定。此外,模板參數(shù)中還可以出現(xiàn)確定類型參數(shù),稱為非類型參數(shù)。例:template<typenameT1,typenameT2,typenameT3,intT4>T1fx(T1a,T2b,T3c){…}在傳遞實(shí)參時(shí),非類型參數(shù)T4只能使用常量,如67.2.1

函數(shù)模板的定義③模板類型參數(shù)關(guān)鍵字template

<typenameT1,classT2>。這里的class和typename含義相同,與類沒有任何關(guān)系,它僅表示T是一個(gè)類型參數(shù),可以是任何數(shù)據(jù)類型,如int、float、char等,或者用戶定義的struct、enum或class等自定義數(shù)據(jù)類型。建議用typename,以示區(qū)別。④模板類與普通類文件組織的區(qū)別普通函數(shù)或類通常把函數(shù)或類的聲明放在頭文件中,把實(shí)現(xiàn)代碼放在另一個(gè)實(shí)現(xiàn)文件中,以達(dá)到接口與實(shí)現(xiàn)分離的目的。模板(包括函數(shù)模板和類模板)則不一樣,由于在用模板創(chuàng)建(實(shí)例化)模板函數(shù)或模板類時(shí),編譯器必須掌握函數(shù)模板或類成員函數(shù)模板的確切定義。因此,必須把模板的聲明和定義保存在同一文件中,通常保存在同一頭文件中。7.2.2函數(shù)模板的實(shí)例化1、實(shí)例化發(fā)生的時(shí)機(jī)模板實(shí)例化發(fā)生在調(diào)用模板函數(shù)時(shí)。當(dāng)編譯器遇到程序中對(duì)函數(shù)模板的調(diào)用時(shí),它才會(huì)根據(jù)調(diào)用語句中實(shí)參的具體類型,確定模板參數(shù)的數(shù)據(jù)類型,并用此類型替換函數(shù)模板中的模板參數(shù),生成能夠處理該類型的函數(shù)代碼,即模板函數(shù)。7.2.2函數(shù)模板的實(shí)例化函數(shù)模板實(shí)例化情形7.2.2函數(shù)模板的實(shí)例化2、當(dāng)多次發(fā)生類型相同的參數(shù)調(diào)用時(shí),只在第1次進(jìn)行實(shí)例化。對(duì)min模板的函數(shù)調(diào)用:intx=min(2,3);inty=min(3,9);intz=min(8,5);編譯器只在第1次調(diào)用時(shí)生成模板函數(shù),當(dāng)之后遇到相同類型的參數(shù)調(diào)用時(shí),不再生成其他模板函數(shù),它將調(diào)用第1次實(shí)例化生成的模板函數(shù)。template<classT>Tmin(Ta,Tb){return(a<b)?a:b;}Intmin(inta,intb){return(a<b)?a:b;}3、實(shí)例化的方式隱式實(shí)例化編譯器能夠判斷模板參數(shù)類型時(shí),自動(dòng)實(shí)例化函數(shù)模板為模板函數(shù)template<typenameT>Tmax(T,T);…inti=max(1,2);floatf=max(1.0,2.0);charch=max(‘a(chǎn)’,‘A’);…隱式實(shí)例化,表面上是在調(diào)用模板,實(shí)際上是調(diào)用其實(shí)例。7.2.2函數(shù)模板的實(shí)例化顯式實(shí)例化時(shí)機(jī)編譯器不能判斷模板參數(shù)類型或常量值需要使用特定數(shù)據(jù)類型實(shí)例化語法形式模板名稱<數(shù)據(jù)類型,…,常量值,…>(參數(shù))其中數(shù)據(jù)類型提供給類型參數(shù),常量值提供給非類型參數(shù)示例1template<classT>Tmax(T,T);…inti=max(1,‘2’);//error:datatypecan’tbededucedinti=max<int>(1,‘2’);…7.2.2函數(shù)模板的實(shí)例化7.2.3模板參數(shù)1、模板參數(shù)匹配的問題C++在實(shí)例化函數(shù)模板的過程中,只是簡單地將模板參數(shù)替換成調(diào)用實(shí)參的類型,并以此生成模板函數(shù),不會(huì)進(jìn)行參數(shù)類型的任何轉(zhuǎn)換!7.2.3模板參數(shù)【例7-2-01】求最大值的函數(shù)模板。//Eg.cpp#include<iostream>usingnamespacestd;template<classT>Tmax(Ta,Tb){ return(a>b)?a:b;}voidmain(){ doublea=2,b=3.4; floatc=5.1,d=3.2; cout<<"2,3.2的最大值是:"<<max(2,3.2)<<endl; cout<<"ac的最大值是:"<<max(a,c)<<endl; cout<<"'a',3的最大值是:"<<max('a',3)<<endl;}7.2.3模板參數(shù)編譯本程序,將會(huì)產(chǎn)生3個(gè)編譯錯(cuò)誤:C2782,“Tmax(T,T)”:模板參數(shù)“T”不明確……在普通函數(shù)的調(diào)用過程中,C++會(huì)對(duì)類型不匹配的參數(shù)進(jìn)行隱式的類型轉(zhuǎn)換。但是,模板實(shí)例化過程中不會(huì)進(jìn)行任何形式的參數(shù)類型轉(zhuǎn)換,從而導(dǎo)到模板函數(shù)的參數(shù)類型不匹配,因此產(chǎn)生上述編譯錯(cuò)誤。7.2.3模板參數(shù)模板參數(shù)不匹配的解決方法(1)在模板調(diào)用時(shí)進(jìn)行參數(shù)類型的強(qiáng)制轉(zhuǎn)換cout<<max(double(2),3.2)<<endl;(2)顯式指定函數(shù)模板實(shí)例化的類型參數(shù)cout<<max<double>(2,3.2)<<endl;cout<<max<int>('a',3)<<endl;(3)指定多個(gè)模板參數(shù)【例7-2】用兩個(gè)模板參數(shù)實(shí)現(xiàn)求最大值的函數(shù)。#include<iostream>usingnamespacestd;template<classT1,classT2>T1max(T1a,T2b){ return(a>b)?a:b;}voidmain(){ doublea=2,b=3.4; floatc=5.1,d=3.2; cout<<"2,3.2的最大值是:"

<<max(2,3.2)<<endl; cout<<"a,c的最大值是:"<<max(a,c)<<endl; cout<<"'a',3的最大值是:"<<max('a',3)<<endl;} 7.2.2函數(shù)模板的實(shí)例化2.類型與非類型模板參數(shù)函數(shù)模板參數(shù)可以是類屬參數(shù),也可以包括普通類型的參數(shù)。

【例7-3】用函數(shù)模板實(shí)現(xiàn)數(shù)組的選擇法排序,//Eg7-3.cpp#include<iostream>usingnamespacestd;template<classT>voidsort(T

&a,intn){ for(inti=0;i<n;i++){ intp=i; for(intj=i;j<n;j++)if(a[p]<a[j])p=j;intt=a[i]; a[i]=a[p]; a[p]=t; }}T是類型參數(shù),n是非類型參數(shù)template<classT>voiddisplay(T&a,intn){ for(inti=0;i<n;i++)cout<<a[i]<<"\t"; cout<<endl;}

voidmain(){ inta[]={1,41,2,5,8,21,23}; charb[]={'a','x','y','e','q','g','o','u'}; sort(a,7); sort(b,8); display(a,7); display(b,8);}程序運(yùn)行結(jié)果如下:41 23 21 8 5 2 1 y x u q o g e a向模板函數(shù)傳遞非類型參數(shù)時(shí)只能傳遞常量3.模板參數(shù)的作用域模板參數(shù)遵循普通的作用域范圍規(guī)則:模板參數(shù)的可用范圍在其聲明之后,直到模板聲明或定義結(jié)束之前;同局部變量一樣,模板參數(shù)會(huì)隱藏外層作用域中聲明的相同名稱。但與普通函數(shù)不同的是,在模板內(nèi)不能重用模板參數(shù)名。structA{};template<typenameA,typenameB>voidf(Aa,Bb){ At=a;//t是typenameA指定的類型 intB;//錯(cuò)誤,重用模板參數(shù)定義變量名稱。}在f模板內(nèi),模板參數(shù)A隱藏了外層作用域定義的結(jié)構(gòu)類型A。7.2.3模板參數(shù)template<typenameT>autof(Ta,Tb){……}針對(duì)本函數(shù)模板,下面的說法正確的是()inta=f(3,4.2);inta=f(4,3),b=f(9,8)會(huì)2次實(shí)例化函數(shù)模板,生成兩個(gè)f函數(shù)。inta=f(“abc”,”123”);inta=f<double>f(3,5.4);ABCD提交單選題1分7.3類模板7.3.1類模板的概念類模板可用來設(shè)計(jì)結(jié)構(gòu)和成員函數(shù)完全相同,但所處理的數(shù)據(jù)類型不同的通用類。如棧,雙精度棧:

classdoubleStack{ private: doubledata[size]; public:

push(double);doublepop()doubletop();};這些棧除了數(shù)據(jù)類型之外,操作完全相同,就可用類模板實(shí)現(xiàn)。

字符棧:

classcharStack{ private: chardata[size]; …… };public:

push(char);charpop();chartop();};1、類模板的聲明template<typenameT1,typenameT2,…>class類名{

…… //類成員的聲明與定義}其中T1、T2是類型參數(shù)類模板中可以有多個(gè)模板參數(shù),包括類型參數(shù)和非類型參數(shù)7.3.2類模板的定義7.3.2類模板的定義非類型參數(shù)是指某種具體的數(shù)據(jù)類型,在調(diào)用模板時(shí)只能為其提供用相應(yīng)類型的常數(shù)值。template<classT1,classT2,intT3>T1、T2是類型參數(shù),T3是非類型參數(shù)。在實(shí)例化時(shí),必須為T1、T2提供一種數(shù)據(jù)類型,為T3指定一個(gè)整常數(shù)(如10),該模板才能被正確地實(shí)例化。非類型參數(shù)是受限制通??梢允钦汀⒚杜e型、對(duì)象或函數(shù)的引用,以及對(duì)象、函數(shù)或類成員的指針但不允許用浮點(diǎn)型(或雙精度型)、類對(duì)象或void作為非類型參數(shù)。2、類模板的成員函數(shù)的定義方法1:在類模板外定義,語法template<模板參數(shù)列表>

返回值類型類模板名<模板參數(shù)名稱列表>::成員函數(shù)名(參數(shù)列表)

{

……

};其中<模板參數(shù)列表>引入的“類型標(biāo)識(shí)符”作為數(shù)據(jù)類型使用<模板參數(shù)名稱列表>引入的“普通數(shù)據(jù)類型常量”作為常量使用方法2:直接在模板內(nèi)定義成員函數(shù),與常規(guī)成員函數(shù)的定義方法相同。7.3.2類模板的定義【例7-4】設(shè)計(jì)一個(gè)堆棧的類模板Stack,在模板中用類型參數(shù)T表示棧中存放的數(shù)據(jù),用非類型參數(shù)MAXSIZE代表?xiàng)5拇笮 ?/Eg7-4.cpp//Stack.htemplate<classT,intMAXSIZE>

classStack{private: Telems[MAXSIZE];

inttop; public: Stack(){top=0;}; voidpush(Te);

Tpop();

boolempty(){returntop==0;}

boolfull(){returntop==MAXSIZE;} };template<classT,intMAXSIZE> voidStack<T,MAXSIZE>::push(Te){ if(top==MAXSIZE){ cout<<"棧已滿,不能再加入元素了!"; return; } elems[top++]=e;}template<classT,intMAXSIZE> inlineTStack<T,MAXSIZE>::pop(){ if(top<=0){ cout<<"棧已空,不能再彈出元素了!"<<endl; return0; } top--; returnelems[top];}7.3.2類模板的定義<模板參數(shù)列表><模板參數(shù)名稱列表>7.3.3類模板實(shí)例化1、類模板實(shí)例化的內(nèi)容包括模板實(shí)例化和成員函數(shù)實(shí)例化2、類模板實(shí)例化的時(shí)間當(dāng)用類模板定義對(duì)象時(shí),引起類模板的實(shí)例化3、實(shí)例化的方法:在實(shí)例化類模板時(shí),如果模板參數(shù)是類型參數(shù),則必須為它指定具體的類型;如果模板參數(shù)是非類型參數(shù),則必須為它指定一個(gè)常量值。4、實(shí)例化案例如對(duì)Stack類模板,下面的定義將引起實(shí)例化Stack<int,10>iStack;編譯器實(shí)例化iStack的方法是:數(shù)據(jù)成員實(shí)例化:將Stack模板聲明中的所有數(shù)據(jù)成員的類型參數(shù)T替換成int,將所有的非類型參數(shù)MAXSIZE替換成10,生成了一個(gè)int類型的模板類。成員函數(shù)實(shí)例化:用int替換無參構(gòu)造函數(shù)中的T實(shí)例化出被調(diào)用的構(gòu)造函數(shù)。未被調(diào)用的成員函數(shù)不被實(shí)例化(即不生成相應(yīng)的成員函數(shù))classStack{private: intelems[10];

inttop; //棧頂指針public: Stack(){top=0;}; voidpush(inte); //入棧操作

intpop(); //出棧操作

boolempty(){returntop==0;}

boolfull();} };7.3.3類模板實(shí)例化Stack模板能夠?qū)嵗鰺o窮多的模板類7.3.3類模板實(shí)例化7.3.4類模板的使用為了使用類模板對(duì)象,顯式指定模板實(shí)參進(jìn)行模板實(shí)例化。//Eg7-4b.cpp#include"stack.h" //該頭文件的內(nèi)容見例7-4所示的程序清單#include<iostream>usingstd::cout; //只使用std域名空間中的coutusingstd::endl; //只使用std域名空間中的endlvoidmain(){ Stack<int,10>iStack; Stack<char,10>cStack; cout<<"-------intStack----\n"; inti; for(i=1;i<10;i++)iStack.push(i); for(i=1;i<10;i++)cout<<iStack.pop()<<"\t"; cout<<"\n\n-------charStack----\n"; cStack.push('A'); cStack.push('B'); cStack.push('C'); cStack.push('D'); cStack.push('E'); for(i=1;i<6;i++)cout<<cStack.pop()<<"\t"; cout<<endl;}

7.3.4類模板的使用【例7-5】對(duì)例7-4建立的Stack類模板編寫一個(gè)函數(shù)display

,該函數(shù)能夠讀取并顯示Stack模板類建立的棧中的所有元素。//Eg7-5.cpp#include"stack.h"#include<iostream>usingnamespacestd;template<classT>voiddisplay(Stack<T,10>&s){ while(!s.empty()) cout<<s.pop()<<"\t"; cout<<endl;}voidmain(){ Stack<int,10>iStack; cout<<"-------intStack----\n"; for(inti=1;i<10;i++)

iStack.push(i); display(iStack);}7.4模板設(shè)計(jì)中的獨(dú)特問題7.4.1模板參數(shù)類型推導(dǎo)模板參數(shù)常用值類型、左值引用、右值引用等。1.傳值模板參數(shù)值類型模板參數(shù)的形式如下:template<typenameparam>r_typefun(paramp,…){…}調(diào)用fun()時(shí),編譯器根據(jù)傳遞給p的實(shí)參類型推導(dǎo)出模板參數(shù)param的實(shí)際類型,并以此實(shí)例化生成模板函數(shù)。編譯器在推導(dǎo)模板參數(shù)param類型的過程中,會(huì)去除所有加在實(shí)參上的類型限定符(包括const、&和&&)以體現(xiàn)函數(shù)的值形參語義。因?yàn)檫@樣才能夠保證模板函數(shù)值形參可復(fù)制的語義(函數(shù)調(diào)用時(shí)將實(shí)參的值復(fù)制到值形參變量中)。7.4.1模板參數(shù)類型推導(dǎo)【例7-6】模板傳值形參的類型檢測(cè)。//Eg7-6.cpp#include<iostream>#include<memory>#include<typeinfo>usingnamespacestd;template<typenameT>voidf(Tp){cout<<typeid(p).name()<<endl;}

intmain(){inti1=0;int&i2=i1;constint&i3=i1+8;int&&i4=5+7;int*i5=newint(1);unique_ptr<int>i6{newint};f(2);f(i1);f(i2);f(i3); f(i4);f(i5);//f(i6);//unique_ptr不能夠被復(fù)制

f(move(i6));}int//從2int//從i1int//從i2int//從i3int//從i4int*__ptr64//從i5classstd::unique_ptr<int,structstd::default_delete<int>參數(shù)類型7.4.1模板參數(shù)類型推導(dǎo)2.左值引用模板參數(shù)模板參數(shù)的形式如下:template<typenameparam>r_typefun(param&p,…){…}當(dāng)類型參數(shù)Param為可變引用(左值引用)時(shí),可以向它傳遞能夠推斷出地址的實(shí)參,如果是const類型的實(shí)參,將保留它的const限定。但是,不能夠接受字面常量和臨時(shí)變量,這是因?yàn)橐脜?shù)是可以修改實(shí)參值的,但將常量和臨時(shí)變量傳給引用參數(shù),就與該語義相違背了。修改例7.6,將f()的類型參數(shù)改為引用參數(shù)。7.4.1模板參數(shù)類型推導(dǎo)【例7-7】模板傳左值形參的類型檢測(cè)。//Eg7-7.cpp#include<iostream>#include<memory>#include<typeinfo>usingnamespacestd;template<typenameT>voidf(T&p){cout<<typeid(p).name()<<endl;}Intmain(){inti1=0;int&i2=i1;constint&i3=i1+8;int&&i4=5+7;int*i5=newint(1);unique_ptr<int>i6{newint};

intmain(){//f(2);//錯(cuò)誤,

f(i1);//p為int&f(i2);//p為int&f(i3); //p為constint&f(i4);//p為int&,引用折疊:參考例7-8,f(i5);//p為int*&f(i6);//p為unique_ptr<int>*p//f(move(i6));//unique_ptr不能夠被復(fù)制}推出形參p的類型當(dāng)類型參數(shù)為左值引用時(shí),無論實(shí)參是左值還是右值,推斷出的模板參數(shù)都是左值。引用當(dāng)類型參數(shù)是右值引用時(shí),只有當(dāng)實(shí)參也是右值時(shí),推斷出的模板參數(shù)才是右值引用7.4.1模板參數(shù)類型推導(dǎo)3.右值引用模板參數(shù)模板參數(shù)的形式如下:template<typenameparam>r_typefun(param&&p,…){…}形如T&&這樣的右值引用參數(shù),既可以接受左值引用實(shí)參,也可以接受右值引用實(shí)參,通常被稱為轉(zhuǎn)發(fā)引用。修改例7.7,將f()的類型參數(shù)改為右值引用參數(shù)。7.4.1模板參數(shù)類型推導(dǎo)【例7-8】模板傳右值形參的類型檢測(cè)。//Eg7-8.cpp#include<iostream>#include<memory>#include<typeinfo>usingnamespacestd;template<typenameT>voidf(T&&p){cout<<typeid(p).name()<<endl;}Intmain(){inti1=0;int&i2=i1;constint&i3=i1+8;int&&i4=5+7;int*i5=newint(1);unique_ptr<int>i6{newint};

intmain(){//f(2);//錯(cuò)誤,

f(i1);//p為int&f(i2);//p為int&f(i3); //p為constint&f(i4);//p為constint&f(i5);//p為int*&f(i6);//p為unique_ptr<int>*p//f(move(i6));//unique_ptr不能夠被復(fù)制}推出形參p的類型當(dāng)類型參數(shù)為左值引用時(shí),無論實(shí)參是左值還是右值,推斷出的模板參數(shù)都是左值。引用當(dāng)類型參數(shù)是右值引用時(shí),只有當(dāng)實(shí)參也是右值時(shí),推斷出的模板參數(shù)才是右值引用7.4模板設(shè)計(jì)中的獨(dú)特問題7.4.2內(nèi)聯(lián)與常量函數(shù)模板函數(shù)模板和類模板都可以定義為inline和constexpr函數(shù)。方法是將inline和constexpr放在模板參數(shù)列表之后,函數(shù)返回類型之前。template<classT>inlineTmin(Ta,Tb){return(a<b)?a:b;}

template<classT>constexprTmin(Ta,Tb){return(a<b)?a:b;}11C++下面模板聲明則是錯(cuò)誤的,inline關(guān)鍵字的位置不對(duì)。inlinetemplate<classT>Tmin(Ta,Tb){return(a<b)?a:b;}7.4.3默認(rèn)模板實(shí)參

11C++模板參數(shù)可以指定默認(rèn)值(包括函數(shù)模板和類模板)遵守與函數(shù)默認(rèn)值同樣的規(guī)則:一旦為某個(gè)模板參數(shù)指定了默認(rèn)值,則它右邊的模板參數(shù)都應(yīng)該有默認(rèn)值【例7-9】設(shè)計(jì)比較兩個(gè)不同類型數(shù)字大小的函數(shù)模板compare,第二個(gè)模板參數(shù)的類型默認(rèn)為double。當(dāng)?shù)?個(gè)參數(shù)大于第2個(gè)參數(shù)時(shí)返回1,大于第2個(gè)參數(shù)時(shí)返回-1,相等時(shí)返回0。//Eg7-9.cpp#include<iostream>usingnamespacestd;template<typenameT,typenameD=double>//默認(rèn)模板參數(shù)intcompare(Tt=0,Du=0){ if(t>u)return1; elseif(t<u)return-1; elsereturn0;}voidmain(){ cout<<compare(10,'a')<<"\t";//compare<int,char>(10,'a') cout<<compare<int,char>()<<"\t";//compare<int,char>(0,0)

//下面兩次compare調(diào)用都使用了默認(rèn)模板參數(shù)double cout<<compare(20)<<"\t"; //compare<int,double>(20,0), cout<<compare<int>()<<endl; //compare<int,double>(0,0) //compare(); //錯(cuò)誤:不能確定模板參數(shù)T的類型

}7.4.2默認(rèn)模板實(shí)參

11C++程序運(yùn)行的結(jié)果是:-1 0 1 0下面關(guān)于函數(shù)默認(rèn)值正確的是()intf(inta=1,intb,int

c);template<class

T=int,class

T2>Tf1(T

a=0,T2

j){}template<class

T=int,class

T2=char>Tf1(T

a=0,T2

j=‘0’){}intg(inta=0,intk);ABCD提交單選題1分7.4.3仿函數(shù)應(yīng)用1.仿函數(shù)基本概念仿函數(shù)又叫函數(shù)對(duì)象,可以像調(diào)用函數(shù)一樣使用對(duì)象。實(shí)際是類的函數(shù)調(diào)用運(yùn)算符函數(shù)operator()的重載函數(shù)。定義形式:classA{Aoperaotr()(參數(shù)表){…} //仿函數(shù)}與普通函數(shù)區(qū)別:仿函數(shù)可以靈活應(yīng)用于自身或其他函數(shù)。例如:Aobj;obj(…);//調(diào)用仿函數(shù),參數(shù)表與operator()的參數(shù)表相匹配【例7-10】設(shè)計(jì)一個(gè)通用求和、積的函數(shù)模板accumulate(),調(diào)用類模板Add和Mul的仿函數(shù)計(jì)算數(shù)據(jù)區(qū)間的和或積。#include<iostream>#include<vector>usingnamespacestd;template<typenameT>classAdd{public:Toperator()(constT&x,constT&y){returnx+y;}};template<typenameT>classMul{public:Toperator()(constT&x,constT&y){returnx*y;}};template<typenameiter,typenameT,typenamefunction>Taccumulate(iterbegin,iterend,Tinit,functionf){//f是函數(shù)對(duì)象,接收函數(shù)名為參數(shù)for(iterit=begin;it!=end;++it)init=f(init,*it);returninit;}intmain(){vectorv1={2.1,3.1,4.1,5.1,7.1}; //L1,C++17以上標(biāo)準(zhǔn)

vector<double>v2={2.0,3.0,4.0,5.0,7.0}; //L2,C++17之前標(biāo)準(zhǔn)

doublesum=accumulate(v1.begin(),v1.end(),0.0,Add<int>{}); //L3doublemul=accumulate(v2.begin(),v2.end(),1.0,Mul<double>()); //L4cout<<"sum="<<sum<<"\tmul="<<mul<<endl;}}程序運(yùn)行結(jié)果如下:sum=21mul=8407.4.5成員模板1、成員模板的概念可以把類(普通類和類模板)的某些成員函數(shù)設(shè)置為模板,稱為成員模板。2、成員模板使用規(guī)則成員模板的定義方法與普通函數(shù)模板相同;但是,成員模板是類的成員,可以訪問類的所有成員,使用與類成員訪問權(quán)限和作用域限定的相同規(guī)則。成員模板不能是虛函數(shù)。【例7-11】OutArray是一個(gè)數(shù)組輸出的代理類,為它設(shè)計(jì)一個(gè)成員模板,用于輸出指定大小的不同類型數(shù)組值。問題分析重載OutArray類的函數(shù)調(diào)用運(yùn)算符函數(shù)operator()為成員模板,接收模板數(shù)組參數(shù),并輸出該數(shù)組中的數(shù)據(jù)元素。//Eg7-11.cpp#include<iostream>usingnamespacestd;classOutArray{public: OutArray(ostream&o=cout):os(o){} template<typenameT>voidoperator()(T*a,intn){ for(inti=0;i<n;i++) os<<a[i]<<"\t"; os<<endl; }private: ostream&os;};intmain(){ doubled[]={1.2,3.4,5.6,8,9,21}; constchar*c[]={"abc","efg","der","aa"}; OutArrayout;//定義OutArray類對(duì)象 out(d,6);//實(shí)例化OutArray::operator(double*,int) out(c,4);//實(shí)例化OutArray::operator(double*,int) return0;}7.4.5成員模板程序運(yùn)行結(jié)果如下:1.2 3.4 5.6 8 9 21 abc efg der aa7.4.5可變參數(shù)函數(shù)模板

11C++1、關(guān)于可變參數(shù)函數(shù)模板參數(shù)類型和個(gè)數(shù)都不確定的函數(shù)模板,即可變參數(shù)模板。此模板為功能需求明確,但數(shù)據(jù)類型和參數(shù)個(gè)數(shù)不確定的程序設(shè)計(jì)提供了更大的靈活性。2、可變參數(shù)函數(shù)模板的定義方法template<typenameT1,typename...T2>r_typef(T1p,T2...arg){ …… }其中,T2就是可變模板參數(shù),稱為參數(shù)包,可以是零個(gè)或多個(gè)類型不同的模板參數(shù)。7.4.5可變參數(shù)函數(shù)模板

11C++【例7-12】設(shè)計(jì)max函數(shù)模板,能夠從任意多個(gè)數(shù)字中計(jì)算出最大值。//Eg7-12.cpp#include<iostream>usingnamespacestd;template<typenameTmymax(Tt)

//結(jié)束條件,當(dāng)只有一個(gè)參數(shù)就返回

{ returnt;}template<typenameT1,typename...T2>doublemax(T1p,T2...arg){ doubleret=mymax(arg...);//包擴(kuò)展 if(p>ret)returnp; else returnret;}可變參數(shù)模板的運(yùn)行過程和遞歸程序相似。需要定義結(jié)束模板遞歸結(jié)束的函數(shù)模板!intmain(){ cout<<mymax(1,12,3,4,20)<<"\t";//輸出:20 cout<<mymax('5',32,'2',23.0)<<"\t";//輸出:53(‘5’的ASCII) cout<<mymax('a','z',2)<<"\t"; //輸出:122(‘z’的ASCII) cout<<mymax(2,3.2)<<endl; //輸出:3.2 return0;}3、可變參數(shù)函數(shù)模板的執(zhí)行過程(1)包擴(kuò)展可變參數(shù)函數(shù)通常都是遞歸調(diào)用的:函數(shù)執(zhí)行時(shí)先處理包中的第一個(gè)實(shí)參,完成后再調(diào)用包中的剩余實(shí)參調(diào)用函數(shù),稱為包擴(kuò)展。類似于下面的程序結(jié)構(gòu):7.4.5可變參數(shù)函數(shù)模板

11C++可變參數(shù)函模板處理過程return_typef(T1p,T2...arg){

將arg中的第1個(gè)參數(shù)取出給p;f(…arg中除第1個(gè)參數(shù)

之外的其余參數(shù))//遞歸……}例如,“max(‘a(chǎn)’,‘z’,2)”調(diào)用的包擴(kuò)展過程如下,分4次調(diào)用才結(jié)束。mymax('a','z',2);//包擴(kuò)展函數(shù)

mymax('z',2)//包擴(kuò)展函數(shù)

mymax(2)//值為2,結(jié)束遞歸調(diào)用7.4.5可變參數(shù)函數(shù)模板

11C++p=‘a(chǎn)’ret=(‘z’,2)p=‘z’ret=(2)template<classT1,class...T2>doublemymax(T1p,T2...arg){

doubleret=mymax(arg...);

if(p>ret)returnp; else returnret;}mymax(‘a(chǎn)’,‘z’,2)的調(diào)用過程template<classT1,class...T2>doublemymax(T1p,T2...arg){

doubleret=mymax(arg...);

if(p>ret)returnp; else returnret;}mymax('a','z',2);ret=mymax('z',2);ret=mymax(2);P=‘a(chǎn)’;P=‘z’;ret=2;ret=122;return122;“mymax(‘a(chǎn)’,‘z’,2)”(2)包擴(kuò)展結(jié)束為了終止遞歸,通常會(huì)為可變參數(shù)模板定義一個(gè)非可變參數(shù)的普通函數(shù)。比如,例7-12中的“doublemymax()”就是用于結(jié)束遞歸的函數(shù),它會(huì)在變參模板函數(shù)的參數(shù)處理完畢后被調(diào)用到,用于結(jié)束mymax函數(shù)的遞歸調(diào)用。7.4.6可變參數(shù)函數(shù)模板

11C++元編程由來1994年,ErwinUnruh寫了一個(gè)求解小于N的全部素?cái)?shù)的C++程序,該程序并不能通過編譯,但編譯器在錯(cuò)誤信息中顯示出了求解結(jié)果。這個(gè)程序證明了編譯器具有計(jì)算能力,程序的功能并非必須在運(yùn)行期才能夠?qū)崿F(xiàn),在編譯期也是可以實(shí)現(xiàn)的?;靖拍钤幊蹋╩eta-programming)正是基于編譯器具有計(jì)算能力這個(gè)基礎(chǔ)演化出來的一種編程技術(shù),其思想是:利用模板技術(shù),編寫出能夠在編譯期間計(jì)算出運(yùn)行時(shí)需要的常數(shù)、類型、代碼的元模板,該模板能夠讀取、分析、轉(zhuǎn)換或者生成其他程序,甚至在運(yùn)行時(shí)修改程序自身(反射),有人形象地稱之為“編程序的程序”7.4.7元編程的基本概念

11C++【例7-13】設(shè)計(jì)可變參數(shù)的函數(shù)模板mysum(

)計(jì)算任意多個(gè)類型不確定數(shù)字的總和#include<iostream>template<typenameT>Tmysum(Ts){returns;}template<typenameT,typename...P>Tmysum(Tt,P...x){//C++14,可用automysum(Tt,P…x)returnt+mysum(x...);}intmain(){autos1=mysum(2.0f,4.3f,10.1f,-3.6f);autos2=mysum(2,4.3f,10u,-45.2);std::cout<<"s1="<<s1<<std::endl;std::cout<<"s2="<<s2<<std::endl;}7.4.7元編程的基本概念

11C++程序結(jié)果:s1=12.8s2=-2147483648程序運(yùn)行結(jié)果是錯(cuò)誤的,根源是mysum()總是返回第1個(gè)參數(shù)t的類型!如果能夠讓編譯器根據(jù)每次的模板調(diào)用實(shí)參計(jì)算出正確的返回值類型,程序?qū)⑹钦_的。這就是元編程,在編譯期間完成類型計(jì)算!#include<iostream>usingnamespacestd;template<typename...P>structSumType;template<typenameT>structSumType<T>{usingtype=T;};template<typenameT,typename...P> structSumType<T,P...>{usingtype=decltype(T()+typenameSumType<P...>::type());};template<typename...P> usingsumRetType=typenameSumType<P...>::type;

template<typenameT>Tmysum(Ts){returns;}template<typenameT,typename...P>sumRetType<T,P...>mysum(Tt,P...x){returnt+mysum(x...);}intmain(){autos1=mysum(2.0f,4.3f,10.1f,-3.6f);autos2=mysum(2,4.3f,10u,-45.2);std::cout<<"s1="<<s1<<std::endl;std::cout<<"s2="<<s2<<std::endl;}【例7-14】基于元模板的可變參數(shù)函數(shù)模板計(jì)算多類型數(shù)字總和的函數(shù)mysum()。程序結(jié)果:s1=12.8s2=-28.9為編譯器設(shè)計(jì)計(jì)算類型SumType的遞歸算法定義mysum的返回值類型SumType變參的返回類型為:SumType。編譯器會(huì)根據(jù)調(diào)用實(shí)參的類型在編譯期利用上面的算法計(jì)算出SumType的實(shí)際類型,然后再實(shí)例化出具體數(shù)據(jù)類型的mysum函數(shù)//Eg7-15.cpp#include<iostream>#include<type_traits>usingnamespacestd;template<typenameT>Tmysum(Ts){returns;}template<typenameT,typename...P>common_type_t<T,P...>mysum(Tt,P...x){ //C++14returnt+mysum(x...);}intmain(){autos1=mysum(2.0f,4.3f,10.1f,-3.6f);autos2=mysum(2,4.3f,10u,-45.2);cout<<"s1="<<s1<<endl;cout<<"s2="<<s2<<endl;}【例7-15】運(yùn)用C++14標(biāo)準(zhǔn)的common_type_t通用數(shù)據(jù)類型,設(shè)計(jì)泛型可變參數(shù)求和函數(shù)模板。程序結(jié)果:s1=12.8s2=-28.9在C++11的標(biāo)準(zhǔn)頭文件<type_traits>中提供了類似于例7-14中SumType的通用類型comm_type(在C++14及以上標(biāo)準(zhǔn)中的名稱為comm_type_t)此頭文件定義通用模板參數(shù)類型:common_type運(yùn)用comm_type_t和可變參數(shù)函數(shù)模板,改寫后的mysum()版本。兩者具有完全相同的功能。7.4.8模板重載、特化、非模板函數(shù)及調(diào)用次序1.模板重載模板可以被另一個(gè)模板或普通函數(shù)重載同函數(shù)重載的規(guī)則相同,要求重載的同名函數(shù)模板必須具有不同的形參表。【例7-16】設(shè)計(jì)從兩個(gè)數(shù)中找出最大值的函數(shù)模板,并重載該函數(shù)模板,實(shí)現(xiàn)從任意三個(gè)數(shù)中找出最大值的函數(shù)模板。//Eg7-16.cpp#include<iostream>#include<string>usingnamespacestd;template<typenameT>inlineTconst&max(Tconst&a,Tconst&b){ returna<b?b:a;}template<typenameT>inlineTconst&max(Tconst&a,Tconst&b,Tconst&c){ returnmax(max(a,b),c);}intmain(){ inta=5,b=12; strings1="aString1",s2="aZtring2"; constchar*c1="hellowtemplateoverride!"; constchar*c2="hellowC++11!"; constchar*c3="helloweveryone!"; cout<<max(7,42,32)<<endl; //L1 cout<<max(a,b)<<endl; //L2 cout<<max(s1,s2)<<endl; //L3 cout<<max(c1,c2,c3)<<endl; //L4 cout<<max(c1,c3)<<endl; //L5}程序運(yùn)行結(jié)果如下:42 //L1的輸出12 //L2的輸出aZtring2 //L3的輸出helloweveryone! //L4的輸出,錯(cuò)誤helloweveryone! //L5的輸出,錯(cuò)誤L4、L5的錯(cuò)誤原因是重載的max函數(shù)模板不能從char*類型的字符串中找出正確的最大值。解決方法是特化模板或定義正確的變通函數(shù)!2.模板特化(1)模板特化的原因模板雖然能夠?qū)嵗鰧?shí)用于各種數(shù)據(jù)類型的可用函數(shù)或類,但要讓一個(gè)模板實(shí)現(xiàn)對(duì)全部數(shù)據(jù)類型的正確處理,卻不一定做得到。比如,在例7-9中,max模板就不能夠正確計(jì)算字符串的最大值。因?yàn)?,char*類型的字符串需要用strcmp函數(shù)而不是“<”運(yùn)算符比較其大小。為了解決這一問題,C++允許為模板定義針對(duì)某種數(shù)據(jù)類型的替代版本,稱為模板的特化。(2)模板特化的語法形式template<>用具體類型替換模板參數(shù)的函數(shù)模板或類模板<>中不需要任何內(nèi)容,表示模板特化。(3)特化模板的設(shè)計(jì)方法特化模板必須與原模板具有相同的結(jié)構(gòu),在設(shè)計(jì)某種數(shù)據(jù)類型的特化模板時(shí),只需要把原模板中的類型參數(shù)替換成指定數(shù)據(jù)類型后,重新編寫函數(shù)模板(或類模板成員函數(shù))的實(shí)現(xiàn)代碼就行了。7.4.8模板重載、特化、非模板函數(shù)及調(diào)用次序【例7-17】為例7-6的max函數(shù)模板提供特化版,找出2個(gè)char*類型字符串中的最大值。解決模板不能正確進(jìn)行字符串大小比較的問題例7-16的模板不能正確正字符串的大小比較,解決方法是在原程序中添加處理constchar*最大值計(jì)算的max特化模板函數(shù)。方法是:用constchar*替換max模板中的T,其余代碼不作任何修改。7.4.5模板重載、特化、非模板函數(shù)及調(diào)用次序不修改程序的任何代碼(包括main函數(shù)),只在原來的程序中添加下面的特化模板//Eg7-17……template<>constchar*const&max(constchar*const&a,constchar*const&b){ returnstrcmp(a,b)<0?b:a;}程序運(yùn)行結(jié)果如下,這次是正確的了!最后兩行是特化模板輸出的。4212aZtring2hellowtemplateoverride!//正確hellowtemplateoverride!//正確7.4.8模板重載、特化、非模板函數(shù)及調(diào)用次序template<typenameT>inlineTconst&max(Tconst&a,Tconst&b){ returna<b?b:a;}3.為模板補(bǔ)充普通函數(shù)針對(duì)模板不能正確處理的特定數(shù)據(jù)類型,除了提供處理該類型的特化版本之外,還可以提供處理該類型的普通函數(shù)版本?!纠?-18】在例7-17中添加從兩個(gè)constchar*類型的字符串中找出最大值的普通max函數(shù)。在例7-17中添加普通max函數(shù),其余代碼不作任何修改,完整的程序代碼如下:7.4.8模板重載、特化、非模板函數(shù)及調(diào)用次序//Eg7-18.cpp#include<iostream>#include<string>usingnamespacestd;template<typenameT>inlineTconst&max(Tconst&a,Tconst&b){ cout<<“3:\t”;returna<b?b:a;}template<typenameT>inlineTconst&max(Tconst&a,Tconst&b,Tconst&c){ returnmax(max(a,b),c);}template<>//特化constchar*const&max(constchar*const&a,constchar*const&b){ cout<<“2:\t”;returnstrcmp(a,b)<0?b:a;}inlinecharconst*max(charconst*a,charconst*b){

cout<<“1:\t”;returnstd::strcmp(a,b)<0?b:a;}intmain(){inta=5,b=12;strings1="aString1",s2="aZtring2";constchar*c1="hellowtemplateoverride!";constchar*c2="hellowC++11!";constchar*c3="helloweveryone!";cout<<max(7,42,32)<<endl;//L1,輸出: 42cout<<max(a,b)<<endl;//L2,輸出: 12cout<<max(s1,s2)<<endl;//L3,輸出: aZtring2cout<<max(c1,c2,c3)<<endl;//L4,輸出:hellowtemplateoverride!cout<<max(c1,c3)<<endl;//L5,輸出:hellowtemplateoverride!}7.4.8模板重載、特化、非模板函數(shù)及調(diào)用次序3:3:423:123:aZtring22:2:hellowtemplateoverride!1:hellowtemplateoverride!4.函數(shù)參數(shù)匹配與調(diào)用次序當(dāng)一個(gè)程序同時(shí)擁有重載模板、特化模板和普通重載函數(shù),編譯器的選擇次序如下:(1)在眾多符合調(diào)用條件的函數(shù)中選擇最佳匹配的函數(shù),

在匹配非模板函數(shù)時(shí)會(huì)進(jìn)行參數(shù)類型轉(zhuǎn)換。(2)如果模板函數(shù)、模板特化函數(shù)和普通函數(shù)都符合函數(shù)調(diào)用要求,按以下次序調(diào)用:優(yōu)先調(diào)用普通函數(shù);如果沒有普通函數(shù),優(yōu)先調(diào)用模板特化函數(shù);當(dāng)沒有普通函數(shù)和特化模板函數(shù)時(shí)才調(diào)用模板函數(shù)。如果有多個(gè)重載模板函數(shù)都符合要求,就選擇精確匹配的模板函數(shù);如果多個(gè)模板函數(shù)都差不多,就產(chǎn)生二義性錯(cuò)誤。7.4.8模板重載、特化、非模板函數(shù)及調(diào)用次序當(dāng)程序中同時(shí)有模板函數(shù)、模板特化函數(shù)、普通函數(shù)時(shí),其調(diào)用次序是()。模板函數(shù)→特化函數(shù)→普通函數(shù)特化函數(shù)→模板函數(shù)→普通函數(shù)普通函數(shù)→特化函數(shù)→模板函數(shù)模板函數(shù)→特化函數(shù)→普通函數(shù)ABCD提交單選題1分7.5STLSTL就是標(biāo)準(zhǔn)模板庫(StandardTemplateLibrary),是惠普實(shí)驗(yàn)室開發(fā)的一系列軟件的統(tǒng)稱。STL當(dāng)前已是C++的一部分,因此不用安裝額外的庫文件本質(zhì)上講,STL是一些“容器”、算法和其他一些組件的集合,其目的是標(biāo)準(zhǔn)化組件,減少重復(fù)開發(fā),可以使用現(xiàn)成的組件。。在C++標(biāo)準(zhǔn)中,常用STL庫被組織為下面的13個(gè)頭文件:<algorithm>、<deque>、<functional>、<iterator>、<vector>、<list>、<map>、<memory.h>、<numeric>、<queue>、<set>、<stack>和<u

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論