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

文章介绍了C++中的模板特性,包括非类型模板参数的使用,如在Array类中的应用;详细阐述了模板特化,包括函数模板特化和类模板特化,如Date类的比较问题解决;并讨论了模板分离编译的概念,解释了链接错误的原因及解决方法。
摘要由CSDN通过智能技术生成

👍作者主页:进击的1++
🤩 专栏链接:【1++的C++初阶】

一,非类型模板参数

模板参数分为类类型模板参数与非类型模板参数。
类类型形参:出现在模板参数列表中,跟在class或typenam的后面的参数类型。
非类型形参:就是用一个常量作为模板的一个参数,在模板中可将该参数当成常量来使用。要注意的是:此常量必须为整型。
例:

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

在这里插入图片描述

二,模板特化

模板特化有函数模板特化和类模板特化。
函数模板特化:
我们先来看代码:

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;
	}

在这里插入图片描述
当我们要进行某些特殊的比较时就会发生以上这种情况—>当我们想通过指向对象的指针比较日期大小时,结果就会有问题,为了解决这种问题,就有了模板特化。
解决上述问题,我们有如下代码:

template<class T>
	bool less(T& a, T& b)
	{
		return a < b;
	}

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

在这里插入图片描述
类模板特化:
类模板特化又有:全特化与偏特化。
全特化:
全特化即将模板参数列表中的所有参数都确定化。
我们直接来看代码:

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}

在这里插入图片描述

偏特化:
偏特化即对模板参数进一步进行条件限制的特化版本。
其有两种表现方式,先来看第一种:

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。
这种表现方式,我们叫做部分特化。
接下来来看第二种:

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函数,因此就会发生链接错误。

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

template<class T>
int func(T a)
{
	return 0;
}
template<>
int func<int>(int a)
{
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的1++

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值