函数模板的简单知识

交换两个变量的方法有宏定义和函数,他们有各自的优缺点:
(1)宏定义
优:代码重复,适合所有类型
缺:缺少类型检查,宏在预处理阶段就被换,编译器不知道,用宏不安全。
(2)函数:
优:真正的函数调用,编译器会对类型检查,相较于宏安全。
缺:不同类型需要重复定义函数,代码无法复用。
针对以上,C++存在泛型编程,不用考虑具体数据类型。

函数模板的编译
	1.定义点
		模板的头部
	2.调用点 
		模板的实例化后的模板函数

<>模板类型参数列表
T类型 万能的类型 虚假的类型
template
T Sum(T a, T b)
{
return a + b;
}
int main()
{
Sum(10, 20);
Sum(10.1, 20.1);
Sum(‘a’, ‘b’);
return 0;
}

函数模板
1)模板的实例化:调用点用具体的类型去替换虚假类型的过程。
2)模板函数:
a定义点编译模板头部
b调用编译模板函数
3)模板的实参推演:
调用点没有给出的情况下,由系统通过实参推演出来我么需要的类型。

1.函数模板
函数模板是泛型编程在C++中的应用方式之一,是根据实参对参数类型进行推导的,可显示指定参数类型
2.模板函数
3.模板的实例化 
4.模板的实参演绎
5.模板的特例化
   1)完全特例化,是全特例化,有函数模板和类模板
   2)部分特例化,是偏特例化,有类模板
       注意模板重载
6.模板的类型参数
7.模板的非类型参数
   1)常量
   2)浮点型和类类型
8.接收不明确类型的返回值
9.模板的默认值
10.模板的重载
 1)普通函数版本
 2)模板函数
 3)模板特例化版本
 我们在编写程序时,编译器会优先去调用普通函数,但是当函数模板有更好的匹配时或使用限定符<>时,编译器就会去匹配函数模板。以上编译器调用顺序是:
 1)>3) >2)
11.模板的显示实例化
    C++中,函数模板的声明与定义一般写在头文件中,若分开写函数类中声明与定义,如.h 和.cpp中一个声明了某个成员函数一个定义某个函数,互惠导致连接错误,故一般写在.h里。

模板的显示实例化
template int Sum(int, int);
template double Sum(double, double);
/*
int Sum(int a, int b)
{
return a + b;
}
*/

模板函数
bool Compare(int a, int b)
{
return a > b;
}
int main()
{
Compare(10, 20);
return 0;
}

template < typename >
T* getData()
{
return new T();//return new int();
}
int main()
{
//Compare(10, 20.1);//int,double 二义性
//Compare(10, 20);//int,int
//Compare(10.1, 20.1);//double,double
int* p = getData();
return 0;
}
实参推演的注意事项
1.不能产生二义性
2.有实参推演依据
<> 模板类型参数列表 ,typename来定义,Compare是模板名

一趟调用过程中,
	一个模板类型参数只能用一个类型来替换
1.编译模板头部
	两个形参需要相同的类型  
2.调用点
	没有给出用来实例化的类型
	实参推演 
5.模板类型参数
	typename | class定义
	<>模板类型参数列表中处理机制一模一样
	早期
	我们使用class定义模板类型参数
	后期
	我们使用typename定义模板类型参数

template < typename>
class Node//Node不是类,是模板名称 Nude<>
{
public:
Node< T >(T val = T())
:mdata(val),pnext(NULL)
{}
private:
T mdata;
Node< T >* pnext;
}

编写一个程序,实现一个排序函数 ,要求任意类型的数据都能用来排序 。代码如下:
template<typename T, int len>
void Sort(T arr[])
{
len = 5;//常量
T tmp = T();
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}

int main()
{
int arr[] = { 213, 23, 4, 36, 45, 55 };
Sort<int, 6>(arr);
return 0;
}


template//class T//类名 类类型
void Sort(T arr[], int len)
{
T tmp;
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}

template
void Show(T arr[], int len)
{
for (int i = 0; i < len; i++)
{
std::cout << arr[i] << " ";
}
std::cout << std::endl;
}
int main()
{
double arr[] = { 1.1, 321.2, 4.3, 346, 56, 87, 0.5 };
int len = sizeof(arr) / sizeof(arr[0]);
Sort(arr, len);//int*
Show(arr, len);
return 0;
}

类模板 建议
	除了构造和析构以外 
		其他地方都加上模板类型参数

编写一个程序:
使用类模板实现一个栈 ,如下:
const int STACK_SIZE = 10;
template
class Stack
{
public:
Stack()
{
mtop = 0;
}
void push(T val)
{
if (full())
{
return;
}
arr[mtop++] = val;
}
bool empty()
{
return mtop == 0;
}
void pop()
{
if (empty())
{
return;
}
mtop–;
}
T top()
{
if (empty())
{
return 0; //x
}
return arr[mtop - 1];
}
private:
bool full()
{
return mtop == STACK_SIZE;
}
T arr[STACK_SIZE];
int mtop;
};

int main()
{
Stack st;
for (int i = 0; i < 3; i++)
{
st.push(i + 1);//1 2 3
}
auto rt = st.top();
st.pop();
std::cout << "rt : " << rt << std::endl;
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值