C++类模板(进阶)

发布于:2024-05-18 ⋅ 阅读:(138) ⋅ 点赞:(0)

struct和class区别

struct:public

class:private

非类型模板参数

注意:

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

2.非类型N传递的是个常量

#include<iostream>

using namespace std;

namespace tt
{
	//非类型模板参数--只支持整形
	//整形数组
	template<class T , size_t N >//非类型模板参数
	class Arr
	{

	private:
		T _arr[N];
	};

}

int main()
{
	tt::Arr<int, 10> arr1;
	return 0;
}

模板的特化

注意:特化不能单独存在一定要有原模板

目标:针对某些类型进行特定的特殊化处理

特化意义:将模糊的模板更加精细的细分,以满足更多需求

eg.运输货物。有大型卡车运输煤炭等,小型货车运输零食等,冷藏车运输冷冻食品等。更加精细的分类,能让我们的现实中的运输效率更快,程序同样如此。

全特化:

将所有模糊类中的(template<class T1,class T2>)类型中的T替换成更加精确的具体类型(Date<double, int>)

当传递参数时,能直接识别到<double, int>这样的类型,就去调用类中特殊处理的函数

注意:此处我们只是将上面模糊的类更加精确定义,属于上面类的一种拓展,不需要再定义一次类中的对象

只需要将上述类模板的具体类型和函数内容更改

格式为:

//类模板特化
namespace tt
{
	template<class T1,class T2>
	class Date
	{
	public:
		Date() { cout << "调用Date<T1,T2>" << endl; }
	private:
		T1 _a;
		T2 _b;
	};
	//特化类模板--全特化
	template<>
	class Date<double, int>
	{
	public:
		Date() { cout << "调用Date<double,int>" << endl; }
	};
}
int main()
{
	tt::Date<int, int> d1;//识别到模糊类调用Date<int, T2>
	tt::Date<double, int> d2;
//识别到将此Date类中有更符合的全特化类调用Date<double,int>
	return 0;
}

偏特化

将模糊类中的(template<class T1,class T2>)类型中的某个/部分T替换成更加精确的具体类型(Date<int, T2>)

将class T1具体特化成int 此时template<>只有一个T2未特化所以是template<class T2>而Date只特化了T1,T2未特化所以留下T2:Date<int, T2>

格式:

//类模板特化
namespace tt
{
	template<class T1,class T2>
	class Date
	{
	public:
		Date() { cout << "调用Date<T1,T2>" << endl; }
	private:
		T1 _a;
		T2 _b;
	};
	//特化类模板--偏特化
	template<class T2>
	class Date<int, T2>
	{
	public:
		Date() { cout << "调用Date<int, T2>" << endl; }
	};
}
int main()
{
	tt::Date<int, int> d1;//调用Date<int, T2>
	tt::Date<double, int> d2;//调用Date<double,int>
	tt::Date<int, double> d3;//调用Date<int, T2>

	return 0;
}

那么我们这个精确,只能精确到换参数的类型吗?

这个精确,你能精确到什么程度就能特化到什么程度

eg.指针的特化

//类模板特化
namespace tt
{
	template<class T1,class T2>
	class Date
	{
	public:
		Date() { cout << "调用Date<T1,T2>" << endl; }
	private:
		T1 _a;
		T2 _b;
	};
	//特化类模板--全特化
	template<>
	class Date<double, int>
	{
	public:
		Date() { cout << "调用Date<double,int>" << endl; }
	};
	//特化类模板--偏特化
	template<class T2>
	class Date<int, T2>
	{
	public:
		Date() { cout << "调用Date<int, T2>" << endl; }
	};
	//特化类模板--偏特化--更精确
	template<>
	class Date<int*, int*>
	{
	public:
		Date() { cout << "调用Date<int*, int*>" << endl; }
	};
	template<class T1>
	class Date<T1, double*>
	{
	public:
		Date() { cout << "调用Date<T1, double*>" << endl; }
	};
	template<>
	class Date<int*, double*>
	{
	public:
		Date() { cout << "调用Date<int*, double*>" << endl; }
	};
}
int main()
{
	tt::Date<int, int> d1;//调用Date<int, T2>
	tt::Date<double, int> d2;//调用Date<double,int>
	tt::Date<int, double> d3;//调用Date<int, T2>
	tt::Date<int*, int*> d4;//调用Date<int*, int*>

	//调用Date<T1, double*>或调用Date<int, T2>
	//此时调用的偏特化这两种都可以就会报错
	//tt::Date<int, double*> d5;
	//正确
	tt::Date<double, double*> d5;//调用Date<T1, double*>
	
	tt::Date<int*, double*> d6;//调用Date<int*, double*>

	return 0;
}

特殊typename使用

	class Date
	{
	public:
		typedef int* address;
		Date(int year = 2024) :_year(year) {}
		address data() { return &_year; }

	private:
		int _year;
	};
	class Time
	{
	public:
		typedef int* address;
		Time(int hour = 4) :_hour(new int(hour)) {}
		address data() { return _hour; };
	private:
		int* _hour;
	};

	template<typename All>
	void Myprintf( All& a)
	{
		 //错误
		 //All::address it = a.data();
		 //这里的All无法识别用户传来的是什么数据,就不能再去到类里面(内嵌的函数)去取具体的数据
		 //所以在预编译时未知具体类型不能通过
	    //加上typename用于标记,先让编译器记住,传来具体实例化的类型再进去使用
		//正确
		 typename All::address it = a.data();
		 cout << *it << endl;
	}

int main()
{
	Date d;
	Time t;
	Myprintf(d);
	Myprintf(t);
	return 0;
}

使用情况:

只要是在--大模板里面--去取小的类模板--里面的东西就要加 typename,用于让编译器先通过

什么时候实例化?

在传过来具体函数对象类型时


网站公告

今日签到

点亮在社区的每一天
去签到