Visual C++基礎教程課件:模板_第1頁
Visual C++基礎教程課件:模板_第2頁
Visual C++基礎教程課件:模板_第3頁
Visual C++基礎教程課件:模板_第4頁
Visual C++基礎教程課件:模板_第5頁
已閱讀5頁,還剩36頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

模板6.1函數(shù)模板

6.2類模板

習題

6.1函數(shù)模板在程序設計中經(jīng)常會出現(xiàn)這樣的情況:多個函數(shù)的參數(shù)個數(shù)相同,函數(shù)的代碼(功能)也相同,但是它所處理的數(shù)據(jù)的類型不相同。對于這種情況,我們可以使用函數(shù)的重載定義多個函數(shù)名相同的函數(shù)。但即使是設計為重載函數(shù)也只是使用相同的函數(shù)名,函數(shù)體仍然需要分別定義。例如,第2章例2.17中對求絕對值函數(shù)的重載,三個函數(shù)只是參數(shù)的類型和返回值類型不同,其功能完全一樣。實際上,若“提取”出一個可變化的類型參數(shù)T,則三個求絕對值函數(shù)可以“綜合”成為如下的同一個函數(shù):

Tabs(Tx) { returnx>=0?x:-x; }這正是函數(shù)模板的概念。使用函數(shù)模板可以避免函數(shù)體的重復定義,通過創(chuàng)建一個通用的函數(shù),來支持多種不同類型的參數(shù)。實際上,標準C++庫就建立在模板的基礎上。函數(shù)模板的定義形式為:

template<class類型參數(shù)>

返回類型函數(shù)名(參數(shù)表) { 函數(shù)體 }其中,template是聲明模板的關鍵字;“類型參數(shù)”是一個用戶定義的標識符,用來表示任意一個數(shù)據(jù)類型。當在程序中使用函數(shù)模板時,系統(tǒng)將用實際的數(shù)據(jù)類型來代替“類型參數(shù)”,生成一個具體的函數(shù),這個過程稱為模板的實例化,這個由函數(shù)模板生成的具體函數(shù)稱為模板函數(shù)。關鍵字“class”用來指定類型參數(shù),與類無關,也可以使用typename來指定。【例6.1】定義求絕對值的函數(shù)模板,用來求不同數(shù)據(jù)類型值的絕對值。

#include<iostream.h>

template<classT>

Tabs(Tx)

{ returnx>=0?x:-x;

}

voidmain()

{ inti=50; doubled=-3.25; longl=-723358; cout<<abs(i)<<endl; //類型參數(shù)T被替換為int cout<<abs(d)<<endl; //類型參數(shù)T被替換為double cout<<abs(l)<<endl; //類型參數(shù)T被替換為long

}程序運行結果為:

50

3.25

723358

函數(shù)模板可以像一般函數(shù)那樣直接使用。函數(shù)模板在使用時,編譯器根據(jù)函數(shù)的參數(shù)類型來實例化類型參數(shù),生成具體的模板函數(shù)。因此,程序中生成了三個模板函數(shù):intabs(int),doubleabs(double)和longabs(long)。說明:

(1)在定義函數(shù)模板時,template所在的行與函數(shù)定義語句之間不允許有別的語句。例如,下面的程序段在編譯時會產(chǎn)生錯誤:

template<classT> inti;//錯誤,中間不允許有別的語句

Tabs(Tx) { returnx>=0?x:-x; }

(2)在函數(shù)模板中允許使用多個類型參數(shù)。當函數(shù)模板中有多個類型參數(shù)時,多個類型參數(shù)間用逗號分隔,且每個類型參數(shù)前都必須有關鍵字class?!纠?.2】具有兩個類型參數(shù)的函數(shù)模板。

#include<iostream.h>

template<classT1,classT2>

voidmyfunc(T1x,T2y)

{ cout<<"x="<<x<<",y="<<y<<endl;

}

voidmain()

{ myfunc(15,"guo"); myfunc(5.3,42L); myfunc("li","yang");

}程序運行結果為:

x=15,y=guo

x=5.3,y=42

x=li,y=yang

此程序中,根據(jù)函數(shù)模板的調用生成了三個模板函數(shù):voidmyfunc(int,char*)、voidmyfunc(double,long)和voidmyfunc(char*,char*)。

(3)函數(shù)模板的參數(shù)除了包含類型參數(shù)外,還可以包含具體的已存在的數(shù)據(jù)類型的參數(shù)?!纠?.3】求數(shù)組元數(shù)的和的函數(shù)模板。

#include<iostream.h>

template<classT>

Tsum(T*array,intsize=0)

{ Ttotal=0; for(inti=0;i<size;i++) total+=array[i]; returntotal;

}

voidmain()

{ intiarray[]={1,2,3,4,5,6,7,8,9,10}; doubledarray[]={1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9,10.10}; cout<<sum(iarray,10)<<endl; //生成模板函數(shù)intsum(int*,int) cout<<sum(darray,10)<<endl; //生成模板函數(shù)doublesum(double*,int)

}

(4)函數(shù)模板可以重載,但要求參數(shù)的個數(shù)不同?!纠?.4】函數(shù)模板的重載。定義兩個同名的函數(shù)模板,分別求一個數(shù)組前size個元素的和與兩個數(shù)組的前size個元素的和。

#include<iostream.h>

template<classType> //求數(shù)組前size個元素的和

Typesum(Type*a,intsize)

{ Typetotal=0; for(inti=0;i<size;i++) total+=a[i]; returntotal;

}

template<classType> //求兩個數(shù)組前size個元素的和

Typesum(Type*a,Type*b,intsize)

{ Typetotal=0; for(inti=0;i<size;i++) total+=a[i]+b[i]; returntotal;

}

voidmain()

{ inta1[10]={1,2,3,4,5,6,7,8,9,10}; inta2[8]={2,4,6,8,10,12,14,16}; doubled[]={1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9,10.10}; cout<<sum(a1,10)<<endl;

//生成模板函數(shù)intsum(int*,int) cout<<sum(d,10)<<endl; //生成模板函數(shù)doublesum(double*,int) cout<<sum(a1,a2,8)<<endl; //生成模板函數(shù)intsum(int*,int*,int)

}

(5)由函數(shù)模板生成的模板函數(shù)沒有數(shù)據(jù)類型轉換的功能,實例化類型參數(shù)的各模板實參之間必須保持完全一致的類型,否則會產(chǎn)生錯誤?!纠?.5】函數(shù)模板的錯誤調用示例。

#include<iostream.h>

template<classT>

voidswap(T&a,T&b)

{ Ttemp; temp=a; a=b; b=temp;

}

voidmain()

{ inti=10,j=20; doublex=4.5,y=8.3; chara='x',b='y'; cout<<"originali,j:"<<i<<''<<j<<endl; swap(i,j); //正確,生成模板函數(shù)voidswap(int,int) cout<<"swappedi,j:"<<i<<''<<j<<endl; cout<<"originalx,y:"<<x<<''<<y<<endl; swap(x,y);//正確,生成模板函數(shù)voidswap(double,double) cout<<"swappedx,y:"<<x<<''<<y<<endl; cout<<"originala,b:"<<a<<''<<b<<endl; swap(a,b); //正確,生成模板函數(shù)voidswap(char,char) cout<<"swappeda,b:"<<a<<''<<b<<endl; cout<<"originali,a:"<<i<<''<<a<<endl; swap(i,a); //錯誤

cout<<"swappedi,a:"<<i<<''<<a<<endl;

}程序中對函數(shù)模板的調用swap(i,a)產(chǎn)生了錯誤,因為編譯器不能確定函數(shù)模板中類型參數(shù)T是int還是char,這里沒有類型的自動轉換,因而產(chǎn)生了二義性。為了解決這種二義性錯誤,可以采用兩種方法:一是采用強制類型轉換(見例6.6),二是采用非模板函數(shù)重載函數(shù)模板(見例6.7)?!纠?.6】

#include<iostream.h>

template<classT>

Tmax(Tx,Ty)

{ returnx>y?x:y; }

voidmain()

{ inti=8; charc='a'; cout<<max(i,int(c))<<endl; //正確,生成模板函數(shù)intmax(int,int) cout<<max(char(i),c)<<endl; //正確,生成模板函數(shù)charmax(char,char)

}【例6.7】用普通函數(shù)重載函數(shù)模板解決例6.5中的錯誤。

#include<iostream.h>

template<classT>

voidswap(T&a,T&b)

{ Ttemp; temp=a; a=b; b=temp;

}

voidswap(int&a,char&b)

{ inttemp; temp=a; a=b; b=temp; cout<<"overloadedswap"<<endl;

}

voidmain()

{ inti=70,j=80; doublex=4.5,y=8.3; chara='x',b='y'; cout<<"originali,j:"<<i<<''<<j<<endl; swap(i,j); //生成模板函數(shù)voidswap(int,int) cout<<"swappedi,j:"<<i<<''<<j<<endl; cout<<"originalx,y:"<<x<<''<<y<<endl; swap(x,y); //生成模板函數(shù)voidswap(double,double) cout<<"swappedx,y:"<<x<<''<<y<<endl; cout<<"originala,b:"<<a<<''<<b<<endl; swap(a,b); //生成模板函數(shù)voidswap(char,char) cout<<"swappeda,b:"<<a<<''<<b<<endl; cout<<"originali,a:"<<i<<''<<a<<endl; swap(i,a); //正確,調用普通函數(shù)voidswap(int,char) cout<<"swappedi,a:"<<i<<''<<a<<endl;}程序運行結果如下:

originali,j:7080

swappedi,j:8070

originalx,y:4.58.3

swappedx,y:8.34.5

originala,b:xy

swappeda,b:yx

originali,a:80y

overloadedswap

wappedi,a:121P用普通函數(shù)重載函數(shù)模板時,普通函數(shù)的參數(shù)可以與函數(shù)模板生成的模板函數(shù)不同。例如本例中,函數(shù)模板不可能生成模板函數(shù)voidswap(int,char);普通函數(shù)的參數(shù)也可以與生成的模板函數(shù)的參數(shù)相同,但此時,重載的普通函數(shù)失去了類型轉換的功能。例如在例6.6中可以用函數(shù)intmax(int,int)對函數(shù)模板進行重載。由于函數(shù)模板Tmax(T,T)也可以生成模板函數(shù)intmax(int,int),因此,重載的普通函數(shù)不能進行參數(shù)類型的轉換。在C++中,函數(shù)模板的調用與同名函數(shù)的調用方式相同,系統(tǒng)按如下順序進行處理:

(1)搜索程序中參數(shù)表與函數(shù)調用完全相同的函數(shù),如果找到就調用它。

(2)檢查函數(shù)模板經(jīng)實例化后是否有相匹配的模板函數(shù),若有就調用它。

(3)檢查是否有函數(shù)可經(jīng)參數(shù)的自動類型轉換后實現(xiàn)參數(shù)匹配,若有則調用它。如果在以上三種情況下都沒有找到匹配的函數(shù),則按出錯處理。6.2類模板函數(shù)模板只能定義非成員函數(shù)。使用類模板可以使得類中的某些數(shù)據(jù)成員和成員函數(shù)的參數(shù)及返回值取任意數(shù)據(jù)類型。例如,我們設計一個堆棧類,用來對某種數(shù)據(jù)類型的數(shù)據(jù)進行堆棧的操作。無論堆棧操作的數(shù)據(jù)是什么類型的值,它的操作方式都是相同的,只不過所操作的數(shù)據(jù)的類型不同。這時,就可以將要操作數(shù)據(jù)的類型進行參數(shù)化,定義一個類模板。類模板定義的格式如下:

template<class類型參數(shù)> class類名

{ //類的說明部分

};

例如,下面是一個簡單類模板的示例。

template<classT>

classMyClass

{ private: Tx; public: voidSetX(Ta) { x=a; } TGetX() { returnx; }

};上面定義的類模板中,所有成員函數(shù)的定義都在類模板的說明部分。如果在類的實現(xiàn)部分定義成員函數(shù),則應使用以下形式:

template<class類型參數(shù)>

函數(shù)返回類型類名<類型參數(shù)>::函數(shù)名(參數(shù)表) { 函數(shù)體 }其中,函數(shù)的返回類型、參數(shù)表中參數(shù)的類型和函數(shù)體類變量的類型都可以是template后說明的“類型參數(shù)”。類模板不代表一個具體的類,而是代表一組類。當使用類模板定義對象時,系統(tǒng)用指定的數(shù)據(jù)類型代替類型參數(shù),從而將類模板實例化為某個具體的類,這稱為模板類。使用類模板定義對象的格式如下: 類名<類型實參>對象名;其中,“類型實參”是任何已存在的數(shù)據(jù)類型,如果類模板帶有多個類型參數(shù),則必須為每一個類型參數(shù)指定相應的類型實參?!纠?.8】用于對堆棧進行操作的類模板。

#include<iostream.h>

template<classType>

classStack

{ private: inttop,length; Type*s; public: Stack(int); ~Stack() { delete[]s; } voidPush(Type); TypePop();

};

template<classType>

Stack<Type>::Stack(intn)

{ s=newType[n]; length=n; top=0;

}

template<classType>

voidStack<Type>::Push(Typea)

{ if(top==length) { cout<<"Stackisfull!"<<endl; return; } s[top]=a; top++;

}

template<classType>

TypeStack<Type>::Pop()

{ if(top==0) { cout<<"stackisempty!"<<endl; return0; } top--; returns[top];

}

voidmain()

{ Stack<int>s1(10); Stack<double>s2(10); Stack<char>s3(10); s1.Push(11); s2.Push(1.1); s1.Push(22); s2.Push(2.2); s1.Push(33); s2.Push(3.3); cout<<"pops1:"; for(inti=0;i<3;i++) cout<<s1.Pop()<<''; cout<<endl; cout<<"pops2:"; for(i=0;i<3;i++) cout<<s2.Pop()<<''; cout<<endl; for(i=0;i<10;i++) s3.Push('A'+i); cout<<"pops3:"; for(i=0;i<10;i++) cout<<s3.Pop(); cout<<endl;

}程序運行結果如下:

pops1:332211

pops2:3.32.21.1

pops3:JIHGFEDCBA

程序中定義了一個類模板Stack。其中,數(shù)據(jù)成員length用來記錄堆棧中數(shù)據(jù)的個數(shù),top用來指示棧頂位置,數(shù)組s用來存放堆棧中的數(shù)據(jù)。使用Push()函數(shù)將數(shù)據(jù)壓入堆棧,使用Pop()函數(shù)彈出棧頂?shù)臄?shù)據(jù)。在主函數(shù)中利用類模板定義了三個對象,分別用來對int、double和char類型的數(shù)據(jù)進行操作。類模板可以有多個模板參數(shù),在關鍵字template后,多個類型參數(shù)間用逗號分隔,且每個類型參數(shù)前都必須有關鍵字class。例如,下面的示例創(chuàng)建使用兩個類型參數(shù)的類模板?!纠?.9】使用兩個類型參數(shù)的類模板示例。

#include<iostream.h>

template<classT1,classT2>

classMyClass

{ private: T1x; T2y; public: MyClass(T1a,T2b) { x=a;y=b; } voidShow() { cout<<"x="<<x<<",y="<<y<<endl; }

};

voidma

溫馨提示

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

評論

0/150

提交評論