【C++】模板

1. 模板参数分类

模板参数分成两种:

一种是 非类型形参 和 类型形参

类型形参:

举例

template<class T>
struct less
{
	bool operator()(const T& x, const T& y)
	{
		return x > y;
	}
};

 

非类型形参:

举例

template<size_t x>
class arry
{
private:
	int _arr[x];
};

这里数组的大小可以被固定住,取决于 x

注意:

  1. 非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量(不可以被修改)来使用 ,常量是整型类型(如:size_t ,int ,long , char 等等)
  2. 非类型的模板参数必须在编译期就能确认结果

2. 模板的特化

对于某些特殊的类型,使用模板可能会得到一些的错误的结果

如:日期类的比较

举例

#include<iostream>
using namespace std;
template<class T>
bool less(const T x, const T y)
{
	 return x > y;
};

int main()
{
   Data t1(2024,3,6);
   Data t2(2021,6,7);
   cout << less(t1,t2) << endl;  //这种比较得到的是正确的
   Data* p1 = new Data(2024,3,6);
   Data* p2 = new Data(2021,6,7);
   cout << less(p1,p2) << endl; //这种比较结果不一定正确
}

分析:

p1 和 p2 都是动态开辟出来的空间,实际上 less 比较的是它们的地址的高低

a. 函数模板特化

函数模板的特化步骤:

1. 必须要先有一个基础的函数模板

2. 关键字template后面接一对空的尖括号<>

3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型

4. 函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误

代码举例

template<class T>
bool less(const T x,const T y)
{
	 return x > y;
};

template<>
bool less<Data *>(const Data *x,const Data *y)
{
	return *x > *y;
};

注意:

一般情况下如果函数模板遇到不能处理或者处理有误的类型,为了实现简单通常都是将该函数直接给出

代码举例

bool less(const Data *x,const Data *y)
{
	return *x > *y;
};

这样的代码的可读性高,容易书写,因为对于一些参数类型复杂的函数模板,特化时直接给出,因此函数模板不建议特化

b. 类模板特化

(1)全特化

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

代码举例

	template<class T1, class T2>
	class AA
	{
	public:
		AA()
		{
			cout << "T1 T2" << endl;
		}
	private:
		T1 _a;
		T2 _b;
	};
	template<>
	class AA<int,char>
	{
	public:
		AA()
		{
			cout << "int char" << endl;
		}
	private:
		int _a;
		char _b;
	};
	void test2()
	{
		AA<int, int> t1;
		AA<int, char> t2;
	}

运行结果:

 

(2)偏特化

偏特化有两种:

一种是 部分特化: 将模板参数类表中的一部分参数特化

代码举例

template<class T1, class T2>
class AA
{
public:
	AA()
	{
		cout << "T1 T2" << endl;
	}
private:
	T1 _a;
	T2 _b;
};
template<class T1>
class AA<T1,char>
{
public:
	AA()
	{
		cout << "T1 char" << endl;
	}
private:
	T1 _a;
	char _b;
};
void test2()
{
	AA<int, int> t1;
	AA<int, char> t2;
}

运行结果:

 另一种是 参数更进一步的限制

代码举例

template<class T1, class T2>
class AA
{
public:
	AA()
	{
		cout << "T1 T2" << endl;
	}
private:
	T1 _a;
	T2 _b;
};
template<class T1,class T2>
class AA<T1*,T2*> // 限制 T1,T2 是指针类型
{
public:
	AA()
	{
		cout << "T1* T2*" << endl;
	}
private:
	T1* _a;
	T2* _b;
};
void test2()
{
	AA<int, int> t1;
	AA<int*, char*> t2;
}

运行结果:

注意:

特化必须在原模板的基础之上,它不是全新的模板

3. 模板分离编译

模板不支持分离编译(声明和定义不在一个文件)

a. 失败原因

分析原因:

预处理阶段:

头文件展开,去掉注释,替换宏,条件编译

编译:

检查语法,生成汇编代码(一串指令)

汇编:

将汇编代码转换成二进制机器码

链接:

合成生成可执行文件

由此我们直到,在编译的时候,无法实例化模板,因为模板参数的类型是无法确定的,也无法生成汇编代码

b. 解决方案

声明和定义都放在同一个.h文件中 

代码举例

test.h

namespace lhy
{
	template<class T>
	class Add
	{
	public:
		Add()
			:x(T())
			, y(T())
		{}
		int add();
	private:
		T x;
		T y;
	};
	template<class T>
	int Add<T> ::add()
	{
		return x + y;
	}
}

test.cpp 

using namespace std;
#include "test.h"
int main()
{
	lhy::Add<int> t;
	cout << t.add() << endl;
}

运行结果:

4. 模板总结

【优点】

1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生

2. 增强了代码的灵活性

【缺陷】

1. 模板会导致代码膨胀问题,也会导致编译时间变长

2. 出现模板编译错误时,错误信息非常凌乱,不易定位错误

相关推荐

  1. c#模板设计模式

    2024-03-16 09:36:04       49 阅读
  2. C++ 模板

    2024-03-16 09:36:04       52 阅读
  3. C++:模板

    2024-03-16 09:36:04       39 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-16 09:36:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-16 09:36:04       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-16 09:36:04       82 阅读
  4. Python语言-面向对象

    2024-03-16 09:36:04       91 阅读

热门阅读

  1. android的Framework

    2024-03-16 09:36:04       48 阅读
  2. Mysql隔离级别的实现

    2024-03-16 09:36:04       39 阅读
  3. pip/huggingface/conda常用命令笔记

    2024-03-16 09:36:04       48 阅读
  4. Elasticsearch(13) match_phrase的使用

    2024-03-16 09:36:04       45 阅读
  5. 5.82 BCC工具之tcpdrop.py解读

    2024-03-16 09:36:04       39 阅读
  6. Springboot如何判断pom.xml中是否加载了某个jar依赖

    2024-03-16 09:36:04       45 阅读
  7. C#简单聊天服务器程序

    2024-03-16 09:36:04       38 阅读