C++入门篇11 模板进阶

一、非类型模板参数

模板参数分为类型形参和非类型形参

  • 类型形参:出现在模板参数列表里,跟在class/typename之后的参数类型名称
  • 非类型参数:就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将参数当作常量来使用
template <class T,size_t N = 100>
class A
{
public:
    A()
        :_size(0)
    {}
    //...
private:
    T _a[N];
    int _size;
};

上面就是一个简单的静态数组的类,N就是一个非类型模板参数

注意:1.浮点数、类对象以及字符串是不允许作为非类型模板参数的 

2.非类型的模板参数必须在编译期就能确认结果

二、模板的特化

概念:在原模版的基础上,针对特殊类型所进行特殊化的实现方式,模板的特化分为函数模板特化和类模板特化

1.函数模拟板的特化

  1. 必须要先有一个基础的函数模板
  2. 关键字template后面接一对空的尖括号<>
  3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型
  4. 函数形参列表必须和模板函数的基础参数类型完全相同
template<class T>
bool Less(T a, T b)
{
	cout << "Less(T a, T b)" << endl;
	return a < b;
}

template<>
bool Less<int*> (int* a, int* b)
{
	cout << "Less<int*>(int* a, int* b)" << endl;
	return *a < *b;
}

//建议直接写出具体函数
/*bool Less(int* a, int* b)
{
	cout << "Less(int* a, int* b)" << endl;
	return *a < *b;
}*/

int main()
{
	int a = 10, b = 20;
	cout << Less(a, b) << endl;
	cout << Less(&a, &b) << endl;
	return 0;
}
注意:一般情况下如果函数模板遇到不能处理或者处理有误的类型,为了实现简单通常都是将该函数数直接给出,不建议使用函数模板特化

 2.模板特化

2.1全特化----将模板参数列表中所有的参数都确定化

template <class T1,class T2>
class A
{
public:
	A()
	{
		cout << "class A" << endl;
	}
private:
	T1 x;
	T2 y;
};

//全特化
template <>
class A<int,char>
{
public:
	A()
	{
		cout << "class A<int,char>" << endl;
	}
private:
	int x;
	char y;
};

2.2偏特化

偏特化:任何针对模板参数进一步进行条件限制设计的特化版本,分为部分特化和参数的进一步限制两种表现形式

2.2.1部分特化---将模板参数列表种的一部分参数特化
//以上面的模板为基础的部分特化
template <class T>
class A<T, char>
{
public:
	A()
	{
		cout << "class A<T, char>" << endl;
	}
private:
	T x;
	char y;
};
2.2.2参数的更进一步的限制
template <class T1,class T2>
class A<T1*, T2*>
{
public:
	A()
	{
		cout << "class A<T1*, T2*>" << endl;
	}
private:
	T1* x;
	T2* y;
};

测试样例---大家可以猜一下下面的对象分别用的是哪个模板实例化的

void test()
{
	A<int*, int*>a1;
	A<int, char>a2;
	A<double, char>a3;
	A<double, double>a4;
}

三、模板的分离编译

1.什么是分离编译

一个程序(项目)有多个源文件共同实现,而每个源文件单独编译生成目标文件,最终将所有目标文件连接起来形成单一的可执行文件的过程成为分离编译模式

2.模板的分离编译

如上图,一般的函数像上面这样写没有啥问题,但是模板这样写就会出错,为什么呢???因为代码在被编译成可执行程序的过程中,会生成符号表,这里面会有函数和函数地址,当调用函数的时候,就会在里面查找,而模板函数在被实例化之前是没有地址的,也就是不会进入符号表,所以当执行程序的时候,找不到该函数,故报错

(解释一下为什么函数模板没有被实例化,因为每个源文件都是单独编译的,在编译test.cpp文件的时候,由于有头文件的声明,Swap函数被认为是在其他文件中,只要在最终生成的符号表中查找就行,而swap.cpp文件中写的函数模板在等待被实例化,所以不会进入符号表)

所以解决方案有两种,如下

1.在模板定义的地方显示实例化(不推荐,只能一个类型一个类型的实例化),如下图

2.将声明和定义写在一起都放在.h中(或.hpp中,就是.h+.cpp文件结合的意思,和.h文件本质一样)

两种方法本质都是为了让函数模板能够成功实例化

类模板的分离编译同函数模板,这里就不多说了

四、模板的总结

【优点】
1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生
2. 增强了代码的灵活性
【缺陷】
1. 模板会导致代码膨胀问题,也会导致编译时间变长
2. 出现模板编译错误时,错误信息非常凌乱,不易定位错误
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值