CPP语法 六---函数模板
-
- [一、 模板](#一、 模板)
-
- [1.1 函数模板](#1.1 函数模板)
- [1.2 重载函数模板](#1.2 重载函数模板)
- [1.3 类模板](#1.3 类模板)
-
- [1.3.1 简单类模板](#1.3.1 简单类模板)
- [1.3.2 默认模板参数](#1.3.2 默认模板参数)
- [1.3.3 为具体类型的参数提供默认值](#1.3.3 为具体类型的参数提供默认值)
- [1.3.4 有界数组模板](#1.3.4 有界数组模板)
- [1.4 模板的使用](#1.4 模板的使用)
-
- [1.4.1 定制模板类](#1.4.1 定制模板类)
- [1.4.2 定制类模板成员函数](#1.4.2 定制类模板成员函数)
一、 模板
模板是c++的高级特性,分为函数模板和类模板。标准模板库(STL)
模板只作用于其下方的类或函数
1.1 函数模板
函数模板定义
cpp
template <类型形式参数表> 返回类型 函数名(形式参数表)
{
... //函数体
}
template <class T>
void fun(T t)
{
... //函数实现
}
template <class type>
type Sum(type xvar,type yvar)
{
return xvar + yvar;
}
//隐式
int result = Sum(10,20);
doouble result = Sum(10.0,20.0);
//显示
int result = Sum<int>(10,20);
double result = Sum<double>(10.0,20.0);
如果两个参数类型不一样,会报错
template 为关键字,表示定义一个模板,尖括号<>表示模板参数。
模板参数主要有两种:一种是模板类型参数,另一种是模板非类型参数。
1.2 重载函数模板
整型数和浮点数编译器可以直接比较,所以使用函数模板也能直接比较。
cpp
#include <iostream >
#include <string >
using namespace std;
template<class Type>
Type min(Type a,Type b)//定义函数模板
{
if(a < b)
return a;
else
return b;
}
char * min(char * a,char * b)// 重载函数模板
{
if(strcmp(a,b))
return b;
else
return a;
}
void main ()
{
cout << "最小值:" << min(10,1) << endl;
cout << "最小值:" << min('a','b') << endl;
cout << "最小值:" << min("hi","mr") << endl;
}
1.3 类模板
类模板代表一族类,是用来描述通用数据类型或处理方法的机制,它使类中的数据成员和成员函数的参数或返回值可以取任意数据类型。类模板可以说是用类生成类,减少类的定义数量。
类模板声明:
cpp
template <类型形式参数表> class 类模板名
{
... //类模板体
};
类模板成员函数定义:
cpp
template <类型形式参数表>
返回类型 类模板名 <类型名>::成员函数名(形式参数列表)
{
... //函数体
}
其中类型形式参数表中的 参数也可以是其他模板。
cpp
template <template <class A> class B>
class cBase
{
private:
B<int> m_n;
}
类模板也可以继承:
cpp
template <class T>
class CDerived public T
{
public:
CDrived();
};
template <class T>
CDerived<T>::CDerived():T()
{
cout<<""<<endl;
}
void main()
{
CDerived<CBase1> D1;
CDerived<CBase1> D1;
}
1.3.1 简单类模板
cpp
#include <iostream>
using namespace std;
template<class T1,class T2>
class MyTemplate
{
T1 t1;
T2 t2;
public:
MyTemplate(T1 tt1,T2 tt2)
{t1 =tt1, t2=tt2;}
void display()
{ cout << t1 << ' ' << t2 << endl;}
};
void main()
{
int a=123;
double b=3.1415;
MyTemplate<int ,double> mt(a,b);
mt.display();
}
1.3.2 默认模板参数
cpp
#include <iostream>
using namespace std;
template <class T1,class T2 = int>
class MyTemplate
{
T1 t1;
T2 t2;
public:
MyTemplate(T1 tt1,T2 tt2)
{t1=tt1;t2=tt2;}
void display()
{
cout<< t1 << ' ' << t2 << endl;
}
};
void main()
{
int a=123;
double b=3.1415;
MyTemplate<int ,double> mt1(a,b);
MyTemplate<int> mt2(a,b);
mt1.display();
mt2.display();
}
1.3.3 为具体类型的参数提供默认值
cpp
#include <iostream>
using namespace std;
template<class T1,class T2,int num= 10 >
class MyTemplate
{
T1 t1;
T2 t2;
public:
MyTemplate(T1 tt1,T2 tt2)
{t1 =tt1+num, t2=tt2+num;}
void display()
{ cout << t1 << ' ' << t2 <<endl;}
};
void main()
{
int a=123;
double b=3.1415;
MyTemplate<int ,double> mt1(a,b);
MyTemplate<int ,double ,100> mt2(a,b);
mt1.display();
mt2.display();
}
1.3.4 有界数组模板
在模板中想要获取下标值,需要重载数组下标运算符 [ ] ,然后使用模板类实例化数组,就可以进行下标越界检测。例如:
cpp
#include <cassert>
template <class T,int b>
class Array
{
T& operator[](int sub)
{
assert(sub >= 0 && sub < b);
}
}
比较模板重载
cpp
#include "stdafx.h"
#include <iostream>
/*
定义一个能够求的模板函数,并重载该模板函数,使其可以比较字符串的大小。
*/
using namespace std;
template<class T>
T max(T a, T b) {
return a>b?a:b;
}
const char * max(const char *a, const char * b) {
if(strcmp(a,b)){
return b;
}
else {
return a;
}
}
int main(int argc, char* argv[])
{
cout << "最大值:" << max(10,1) << endl;
cout << "最大值:" << max('a','b') << endl;
cout << "最大值:" << max("hi","mr") << endl;
return 0;
}
1.4 模板的使用
定义模板类后如果想扩展模板新类的功能,需要对类模板进行覆盖,使模板类能够完成特殊功能。覆盖操作可以针对整个类模板、部分类模板以及类模板的成员函数,这种覆盖操作称为定制。
1.4.1 定制模板类
定制一个类模板,覆盖类模板中定义的 所有 成员。
cpp
#include <iostream>
using namespace std;
class Date
{
int iMonth,iDay,iYear;
char Format[128];
public:
Date(int m=0,int d=0,int y=0)
{
iMonth=m;
iDay=d;
iYear=y;
}
friend ostream& operator<<(ostream& os,const Date t)
{
cout << "Month: " << t.iMonth << ' ' ;
cout << "Day: " << t.iDay<< ' ';
cout << "Year: " << t.iYear<< ' ' ;
return os;
}
void Display()
{
cout << "Month: " << iMonth;
cout << "Day: " << iDay;
cout << "Year: " << iYear;
cout << endl;
}
};
template <class T>
class Set
{
T t;
public:
Set(T st) : t(st) {}
void Display()
{
cout << t << endl;
}
};
class Set<Date>
{
Date t;
public:
Set(Date st): t(st){}
void Display()
{
cout << "Date :" << t << endl;
}
};
void main()
{
Set<int> intset(123);
Set<Date> dt = Date(1,2,3); //还可以写成这样 Set<Date> dt(Date(1,2,3));
intset.Display();
dt.Display();
}
1.4.2 定制类模板成员函数
定制一个类模板,覆盖类模板中指定的成员
cpp
#include <iostream>
using namespace std;
class Date
{
int iMonth,iDay,iYear;
char Format[128];
public:
Date(int m=0,int d=0,int y=0)
{
iMonth=m;
iDay=d;
iYear=y;
}
friend ostream& operator<<(ostream& os,const Date t)
{
cout << "Month: " << t.iMonth << ' ' ;
cout << "Day: " << t.iDay<< ' ';
cout << "Year: " << t.iYear<< ' ' ;
return os;
}
void Display()
{
cout << "Month: " << iMonth;
cout << "Day: " << iDay;
cout << "Year: " << iYear;
cout << std::endl;
}
};
template <class T>
class Set
{
T t;
public:
Set(T st) : t(st) {}
void Display();
};
template <class T>
void Set<T>::Display()
{
cout << t << endl;
}
void Set<Date>::Display()
{
cout << "Date: " << t << endl;
}
void main()
{
Set<int> intset(123);
Set<Date> dt =Date(1,2,3);
intset.Display();
dt.Display();
}