一些函数的执行功能是相同的,但是参数类型和函数返回类型不同,能否为上述这些函数只写出一套代码呢?
方法一:使用宏定义
方法二:使用模板
一、模板(函数模板和类模板):
① 函数模板 实例化 模板函数
②类模板 实例化 模板类,
模板类 实例化 对象
二、函数模板的声明:
template <typename 类型参数>
返回类型 函数名(模板形参表)
{
函数体
}
Or
template <class 类型参数>
返回类型 函数名(模板形参表)
{
函数体
}
但由于关键字class容易与类名混淆,因此一般使用typename.
三、函数模板的使用、
#include <iostream>
template <typename T>
T max(T x,T y)
{
return (x>y?x:y);
}
int main()
{
int a1 = 1 , a2 = 2 ;
double b1 = 1.1, b2 = 2.2;
char c1 = 'a', c2 = 'A';
std::cout<<"Int Max: "<<max(a1,a2)<<std::endl;
std::cout<<"Double Max: "<<max(b1,b2)<<std::endl;
std::cout<<"Char Max: "<<max(c1,c2)<<std::endl;
return 0;
}
与指针有关的函数模板
#include <iostream>
template <typename AT>
AT sum(AT *array, int size=0)
{
AT total = 0;
for(int i=0;i<size;i++)
total+=array[i];
return total;
}
int main()
{
int In_Array[] = { 11,22,33,44,55 };
double Do_Array[] = {11.11,22.22,33.33,44.44,55.55};
std::cout<<"In_Array Sum: "<<sum(In_Array,5)<<std::endl;
std::cout<<"Do_Array Sum: "<<sum(Do_Array,5)<<std::endl;
return 0;
}
在函数中允许使用多个类型参数
例:有两个类型参数的函数模板
#include <iostream>
template <typename para1, typename para2>
void two_para(para1 x,para2 y)
{
std::cout<<x<<std::ends<<y<<std::endl;
}
int main()
{
two_para(99,"zhang");
two_para(123.45,888L);
return 0;
}
模板函数也可以重载
例:函数模板的重载
#include <iostream>
template <typename Type>
Type min(Type x,Type y)
{
return (x<y?x:y);
}
template <typename Type>
Type min(Type x,Type y,Type z)
{
Type t;
t = x<y?x:y;
return (t<z?t:z);
}
int main()
{
int a=10,b=20,c=30;
double e=10.1,f=20.1,g=30.1;
std::cout<<"Int Two Min: "<<min(a,b)<<std::endl;
std::cout<<"Int Three Min: "<<min(a,b,c)<<std::endl;
std::cout<<"Double Two Min: "<<min(e,f)<<std::endl;
std::cout<<"Double Three Min: "<<min(e,f,g)<<std::endl;
return 0;
}
函数模板与同名的非模板函数可以重载。在这种情况下调用顺序为:
先寻找一个参数完全匹配的非模板函数,若找到便调用;若找不到,则寻找函数模板,将其实例化产生一个匹配的模板函数,若找到便调用,否则报错。
例:函数模板与非函数模板的重载
#include <iostream>
template <typename AT>
AT min(AT x,AT y)
{
std::cout<<"Using Model Function."<<std::endl;
return (x<y?x:y);
}
int min(int x,int y)
{
std::cout<<"Using Normal Function."<<std::endl;
return (x<y?x:y);
}
int main()
{
int a1 = 10 , a2 = 20 ;
double b1 = 10.1, b2 = 20.1;
char c1 = 'a' , c2 = 'A' ;
std::cout<<"Int Min: "<<min(a1,a2)<<std::endl;
std::cout<<"Double Min: "<<min(b1,b2)<<std::endl;
std::cout<<"Char Min: "<<min(c1,c2)<<std::endl;
return 0;
}
四、类模板
可以通过使用类模板来简化那些功能相同但数据类型不同的类的声明
五、类模板的声明
template <typename 类型参数>
class 类名
{
类成员声明
}
Or
template <class 类型参数>
class 类名
{
类成员声明
}
六、类模板的使用
#include <iostream>
using namespace std;
template <typename T>
class Three
{
private:
T x,y,z;
public:
Three(T a,T b,T c)
{ x = a; y = b; z = c; }
T sum()
{ return x+y+z; }
};
int main()
{
Three <int> sum3_1(3,5,7);
Three <double> sum3_2(12.34,34.56,56.78);
cout<<"Int Three sum is: "<<sum3_1.sum()<<endl;
cout<<"Double Three sum is: "<<sum3_2.sum()<<endl;
return 0;
}
在类模板体外定义成员函数的一般形式:
template <typename 类型参数>
函数类型 类名<类型参数>::成员函数名(形参表)
{
...
}
在类模板体外定义成员函数
#include <iostream>
using namespace std;
template <typename T>
class Three
{
private:
T x,y,z;
public:
Three(T a,T b,T c);
T sum();
};
template <typename T>
Three<T>::Three(T a,T b,T c)
{
x = a;
y = b;
z = c;
}
template <typename T>
T Three<T>::sum()
{
return x+y+z;
}
int main()
{
Three <int> sum3_1(3,5,7);
Three <double> sum3_2(12.34,34.56,56.78);
cout<<"Int Three sum is: "<<sum3_1.sum()<<endl;
cout<<"Double Three sum is: "<<sum3_2.sum()<<endl;
return 0;
}
栈类模板的使用
#include <iostream>
using namespace std;
const int size = 10;
template <typename Type>
class Stack
{
private:
Type stck[size];
int tos;
public:
void init()
{ tos = 0; }
void push(Type ch);
Type pop();
};
template <class Type>
void Stack<Type>::push(Type ob)
{
if(tos == size)
{
cout<<"Stack is full."<<endl;
return;
}
stck[tos++] = ob;
}
template <class Type>
Type Stack<Type>::pop()
{
if(tos == 0)
{
cout<<"Stack is empty."<<endl;
return 0;
}
return stck[--tos];
}
int main()
{ // 字符栈
Stack <char> s1,s2;
int i;
s1.init();
s2.init();
s1.push('a');
s2.push('x');
s1.push('b');
s2.push('y');
s1.push('c');
s2.push('z');
for(i=0;i<3;i++) cout<<"pop s1: "<<s1.pop()<<endl;
for(i=0;i<3;i++) cout<<"pop s2: "<<s2.pop()<<endl;
// 整型栈
Stack <int> is1,is2;
is1.init();
is2.init();
is1.push(1);
is2.push(2);
is1.push(3);
is2.push(4);
is1.push(5);
is2.push(6);
for(i=0;i<3;i++) cout<<"pop is1: "<<is1.pop()<<endl;
for(i=0;i<3;i++) cout<<"pop is2: "<<is2.pop()<<endl;
return 0;
}
七、栈类模板的使用(多文件程序编写)
/*---------------------------------------------*/
// 文件Stack.h
#include <iostream>
using namespace std;
template <typename Type>
class Stack
{
private:
int size;
int top;
Type* stackPtr;
public:
Stack(int=10);
~Stack()
{ delete []stackPtr; }
int push(const Type&);
int pop(Type&);
int isFull() const
{ return top==size-1; }
int isEmpty() const
{ return top==-1; }
};
/*---------------------------------------------*/
// 文件Stack.cpp
#include "Stack.h"
template <typename Type>
Stack<Type>::Stack(int s)
{
size = s>0 && s<1000? s:10;
top = -1;
stackPtr = new Type[size];
}
template <typename Type>
int Stack<Type>::push(const Type& item)
{
if(!isFull())
{
stackPtr[++top] = item;
return 1;
}
return 0;
}
template <typename Type>
int Stack<Type>::pop(Type& popValue)
{
if(!isEmpty())
{
popValue = stackPtr[top--];
return 1;
}
return 0;
}
/*---------------------------------------------*/
// 文件 main.cpp
#include "Stack.h"
int main()
{ // 字符栈
Stack <char> charStack;
char c = 'a';
cout<<"Pushing elements onto charStack "<<endl;
while(charStack.push(c))
{
cout<<c<<' ';
c+=1;
}
cout<<endl<<"Stack is full. Cannot push "<<c<<endl
<<"Poping elements from charStack "<<endl;
while(charStack.pop(c))
cout<<c<<' ';
cout<<endl<<"Stack is empty. Cannot pop"<<endl;
// 实型栈
Stack <double> doubleStack(5);
double f=1.1;
cout<<"Pushing elements onto doubleStack "<<endl;
while(doubleStack.push(f))
{
cout<<f<<' ';
f+=1.1;
}
cout<<endl<<"Stack is full. Cannot push "<<f<<endl
<<"Poping elements from doubleStack "<<endl;
while(doubleStack.pop(f))
cout<<f<<' ';
cout<<endl<<"Stack is empty. Cannot pop "<<endl;
// 整型栈
Stack <int> intStack;
int i=1;
cout<<"Pushing elements onto intStack "<<endl;
while(intStack.push(i))
{
cout<<i<<' ';
i+=1;
}
cout<<endl<<"Stack is full. Cannot push "<<i<<endl
<<"Poping elements from intStack "<<endl;
while(intStack.pop(i))
cout<<i<<' ';
cout<<endl<<"Stack is empty. Cannot pop "<<endl;
return 0;
}
/*---------------------------------------------*/