【1++的C++初阶】之模板(二)

👍作者主页:进击的1++

🤩 专栏链接:【1++的C++初阶】

文章目录

一,非类型模板参数

模板参数分为类类型模板参数与非类型模板参数。

类类型形参:出现在模板参数列表中,跟在class或typenam的后面的参数类型。

非类型形参:就是用一个常量作为模板的一个参数,在模板中可将该参数当成常量来使用。要注意的是:此常量必须为整型。

例:

cpp 复制代码
template<class T,size_t N=100>
	class Array
	{
	public:
		void Print()
		{
			cout << "print" << endl;
		}
	private:
		T arr[N];
	 
	};

二,模板特化

模板特化有函数模板特化和类模板特化。
函数模板特化:

我们先来看代码:

cpp 复制代码
namespace hyp
{
	template<class T1, class T2>
	bool less(T1& a, T2& b)
	{
		return a < b;
	}
	
	class Date
	{
	public:

		Date(int year, int month, int day)
			:_year(year)
			,_month(month)
			,_day(day)
		{}

			bool operator<(const Date& d)const
		{
			if (_year < d._year)
			{
				return true;
			}
			else if (_year == d._year)
			{
				if (_month < d._month)
				{
					return true;
				}
				else if (_month == d._month)
				{
					if (_day < d._day)
					{
						return true;
					}
					else
						return false;
				}
				else
					return false;
			}
			else
				return false;

		}
		void Print()
		{
			cout << "print" << endl;
		}

	private:
		int _year;
		int _month;
		int _day;

	};

}

	int main()
	{
		hyp::Date a1(2023, 7, 25);
		hyp::Date a2(2023, 7, 4);
		hyp::Date a3(2023, 7, 16);
		hyp::Date* p1 = &a1;
		hyp::Date* p3 = &a3;
		hyp::Date* p2 = &a2;

		cout << hyp::less(a1, a2);
		cout << hyp::less(p3, p2);

		return 0;
	}

当我们要进行某些特殊的比较时就会发生以上这种情况--->当我们想通过指向对象的指针比较日期大小时,结果就会有问题,为了解决这种问题,就有了模板特化。

解决上述问题,我们有如下代码:

cpp 复制代码
template<class T>
	bool less(T& a, T& b)
	{
		return a < b;
	}

	template<>
	bool less<Date*>(Date*& a, Date*& b)
	{
		return *a < *b;
	}


类模板特化:

类模板特化又有:全特化与偏特化。
全特化:

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

我们直接来看代码:

cpp 复制代码
template<class T1, class T2>
	class Date
	{
	public:
		void Print()
		{
			cout << "template<class T1,class T2>" << endl;
		}
	private:
		T1 a;
		T2 b;

	};

	template<>
	class Date<int,char>
	{
	public:
		void Print()
		{
			cout << "template<int,char>" << endl;
		}
	private:
		int a;
		char b;

	};

}

	int main()
	{
		hyp::Date<int, int> d1;
		d1.Print();
		hyp::Date<int, char> d2;
		d2.Print();
		hyp::Date<double, char> d3;
		d3.Print();
		return 0;

	}

偏特化:

偏特化即对模板参数进一步进行条件限制的特化版本。

其有两种表现方式,先来看第一种:

cpp 复制代码
template<class T1, class T2>
	class Date
	{
	public:
		void Print()
		{
			cout << "template<class T1,class T2>" << endl;
		}
	private:
		T1 a;
		T2 b;

	};

	template<class T1>
	class Date<T1,char>
	{
	public:
		void Print()
		{
			cout << "template<T1,char>" << endl;
		}
	private:
		T1 a;
		char b;

	};

在上述代码中,我们将第二个参数特化为char。

这种表现方式,我们叫做部分特化。

接下来来看第二种:

cpp 复制代码
template<class T1, class T2>
	class Date
	{
	public:
		void Print()
		{
			cout << "template<class T1,class T2>" << endl;
		}
	private:
		T1 a;
		T2 b;

	};

	template<class T1,class T2>
	class Date<T1*,T2*>
	{
	public:
		void Print()
		{
			cout << "template<T1*,T2*>" << endl;
		}
	private:
		T1 a;
		T2 b;

	};

此种偏特化,对模板参数进行了更进一步的限制。

三,模板分离编译

我们假设有以下场景

当我们运行时,会发现链接错误。这是为什么呢?

在进行预处理时,我们的头文件会展开,在编译时,stu.c文件中的func先会去找有没有这个函数,在预处理阶段,头文件已经在我们的stu.c中展开,因此编译器就认为我们有这个函数,所以会根据某中规则形成符号记录在符号表中。而在func.c文件中编译器没有看到对模板函数的实例化,因此不会产生具体的func函数。所以在链接阶段时,我们在符号表中找不到对应的func函数,因此就会发生链接错误。

解决办法就是将函数的声明与定义放在一起,或者是模板定义的位置显式实例化,还可以使用函数的特化。

cpp 复制代码
template<class T>
int func(T a)
{
	return 0;
}
template<>
int func<int>(int a)
{
	return 0;
}
相关推荐
胖大和尚10 分钟前
Linux C++ xercesc xml 怎么判断路径下有没有对应的节点
xml·linux·c++
achene_ql12 分钟前
缓存置换:用c++实现最不经常使用(LFU)算法
c++·算法·缓存
jiunian_cn13 分钟前
【c++】【STL】queue详解
开发语言·c++·visualstudio
achene_ql34 分钟前
C++ 与 Lua 联合编程
开发语言·c++·lua
CodeWithMe1 小时前
【中间件】brpc_基础_bthread头文件
c++·中间件·rpc
weniry2 小时前
动态库与静态库的区别
开发语言·c++
Le_ee2 小时前
数据结构6 · BinaryTree二叉树模板
数据结构·c++·算法
李匠20243 小时前
C++负载均衡远程调用学习之TCP连接封装与TCPCLIENT封装
c++·网络协议·学习·tcp/ip
小宋要上岸3 小时前
优雅关闭服务:深入理解 SIGINT / SIGTERM 信号处理机制
c++·信号处理·grpc
李匠20244 小时前
C++学习之shell高级和正则表达式
c++·学习