C++模版进阶
创始人
2024-11-11 15:35:38
0

前言

这一篇博客讲一下模版的其他内容,进阶内容,后面就会讲继承了,难度上升

1. 非类型模版参数

所谓非类型模版参数,就是在模版参数列表中,即可以存在类型参数,也可以存在非类型参数

template class Array { private: 	T arr[N]; };  int main() { 	Array a1; 	//这个就表示建立一个100个整型的数组 	Array a1; 	return 0; } 

这个也是根据不同的模版参数,编译器生成不同的类

template class Array { public: 	func() 	{ 		N--; 	} private: 	T arr[N]; };  int main() { 	Array a1; 	a1.func(); 	//这个就表示建立一个100个整型的数组 	Array a1; 	return 0; } 

在这里插入图片描述

还有要值得注意的是,非类型的模版参数是个常量,不可修改的
还有就是模版是不会进行编译的,或者说,只会对模版的外壳进行编译,不会对模版的内部进行编译,所以说模版内部有错误,不管是什么错误都是不会检查出来的,只有在调用那个函数的时候才会检查出来错误
还有值得说的就是,在C++20之前是只支持整型的非类型模板参数的,C++20就支持了内置类型的非类型模板参数
编译器默认是C++14,但是是可以修改的
在这里插入图片描述
在这里插入图片描述

 template class Array { public: 	int func() 	{ 		N--; 	} private: 	//T arr[N]; }; 
	Array a; 

只支持内置类型,不支持自定义类型

2. array

在这里插入图片描述

接下来,我们来认识一下array,array其实就是一个数组的类和模版,和数组没什么区别

	array a; 

这就表示建立了一个10个整型的数组,但是这个和C语言的数组有什么区别吗,区别只有一个,那就是有关越界访问的
在这里插入图片描述
int arr[10],是这样的,会在数组的后面加上一两个位置,这两个位置设置为一些固定值,程序结束时看这些值有没有被改变,如果被改变了的话,说明就越界了,注意,这个报错是在程序结束时才报错

	int arr[10] = { 0 }; 	arr[11] = 10; 

在这里插入图片描述
比如这个更改了后面一个的值就报错说越界了

但是array是只要越界了就会马上报错,虽然比我们直接定义数组有点好处,但是这个array并没有什么用,为什么呢,因为还有vector啊,vector不比array好用多了?
我们再来讲一个其他东西

void PrintVector(const vector& v) { 	vector::const_iterator it = v.begin(); 	while (it != v.end()) 	{ 		cout << *it << " "; 		++it; 	} 	cout << endl; } 

这是一个vector的打印函数,但是它只能打印int的,不能打印其它的,于是我们就可以实现一个打印函数的模板了

template void PrintVector(const vector& v) { 	vector::const_iterator it = v.begin(); 	while (it != v.end()) 	{ 		cout << *it << " "; 		++it; 	} 	cout << endl; } 
	vector a = { 1.1,2.3,3.4,5.3 }; 	PrintVector(a); 

但是我们这样写却不能正常运行

template void PrintVector(const vector& v) { 	typename vector::const_iterator it = v.begin(); 	while (it != v.end()) 	{ 		cout << *it << " "; 		++it; 	} 	cout << endl; } 

在这里插入图片描述
但是我们在前面加上typename就可以正常使用了,为什么呢
第一是因为vector::const_iterator能这样使用的只有静态变量,typedef内容,内部类,到底是哪个呢,因为有T嘛,还没有初始化,所以不知道是什么,加上typename就指定了是那种typedef或者变量
第二就是没有实例化,所以不能随便访问,万一有错呢,所以加上那个东西
反正怎么说呢,记住这个东西就可以了,目前只有这种情况要特殊加上typename

3. 模板的特化

先看个例子

template class myless { public: 	bool operator()(const T& t1, const T& t2) 	{ 		return t1 < t2; 	} }; 
	myless a; 	cout<

在这里插入图片描述
这个可以正常比较

	myless a; 	cout<

在这里插入图片描述
在这里插入图片描述
但这个就无法正常比较了,原因就是底层比较的是指针,开辟空间的指针间的大小是无法确定的
解决办法就是重新建立一个仿函数

template class myless1 { public: 	bool operator()(const T& t1, const T& t2) 	{ 		return *t1 < *t2; 	} }; 
	myless1 a; 	cout<

在这里插入图片描述
这是一种方法,再来个模板,但是我们还有其他方法就是模板特化

3.1 函数模板特化

 template bool Less(T left, T right) { 	return left < right; } 

还是这个函数,还是不能比较指针类的东西,于是就可以特化了

template<> bool Less(int* left, int* right) { 	return *left < *right; } 

函数模板的特化就是这个样子,这个就可以比较int类型的指针了

	cout << Less(new int(1), new int(2)); 

在这里插入图片描述
需要什么就特化什么
在这里插入图片描述
但是函数模板特化有个很坑的点就是参数有const有&还有的时候容易出错,比如上面这个就不行,为什么呢,因为模板的意思是left不能修改,但是特化的意思是left不能修改,所以不一样,所以不行
在这里插入图片描述
把const移到*后面就可以了,还有就是const要在&的前面,因为模板都在前面

3.2 类模板特化

template class Date { public: 	Date() 	{ 		cout << "template" << endl; 	} private: };  template<> class Date { public: 	Date() 	{ 		cout << "class Date" << endl; 	} private: }; 
	Date a; 

在这里插入图片描述
像这种全部模板参数都特化,叫做全特化
下面介绍几个偏特化

template class Date { public: 	Date() 	{ 		cout << "class Date" << endl; 	} private: }; 

这个表示第二个模板参数是double就调用这个

template class Date { public: 	Date() 	{ 		cout << "class Date" << endl; 		cout << typeid(T1).name() << endl; 	} private: }; 
	Date a; 

在这里插入图片描述
这个特化就表示只要是指针就调用这个模板,其中T1和T2不一定是指针,这样是为了以后用T1和T2定义非指针变量
这个的作用就是我们一开始提的,如果传的是Date的话,那么就可以用这个来比较了,T1就是Date,专门针对Date来特化一个

template class Date { public: 	Date() 	{ 		cout << "class Date" << endl; 		cout << typeid(T1).name() << endl; 	} private: }; 
	Date a; 

在这里插入图片描述
这个就表示,只要是引用就调用这个模板,而且T1和T2的类型原理和指针是类似的

4. 模板分离编译

接下来我们讲一下模板分离编译,也就是解释为什么模板类的函数声明与定义不能分开的原因
为什么呢
如果说模板类的函数声明与定义分离,声明在.h中,定义在.cpp中,我们又说过,模板是不会进行编译的,意思是.cpp里面的函数就不会进行连接,也就相当于.cpp里面的内容你都白写了,根本没有用,那么这样的话,你要是使用模板的时候,就会去包含的头文件里面找,结果只有声明没有定义,那么就会出错。
所以最好的解决办法就是不要声明与定义分离

总结

下一篇博客讲继承

相关内容

热门资讯

透视游戏!wepoker免费脚... 透视游戏!wepoker免费脚本咨询(透视)底牌透视挂辅助机器人(可靠开挂辅助揭秘攻略)-哔哩哔哩;...
透视有挂!wepoker有插件... 您好:wepoker有插件这款游戏可以开挂的,确实是有挂的,很多玩家在这款游戏中打牌都会发现很多用户...
透视黑科技!hhpoker为有... 透视黑科技!hhpoker为有挂一直输(透视)底牌透视挂辅助底牌(可靠开挂辅助微扑克教程)-哔哩哔哩...
透视辅助!aapoker可以选... 透视辅助!aapoker可以选牌(透视)底牌透视挂辅助插件(可靠开挂辅助微扑克教程)-哔哩哔哩;aa...
透视透视!wepoker辅助器... 透视透视!wepoker辅助器安装包(透视)底牌透视挂辅助机器人(可靠开挂辅助插件教程)-哔哩哔哩;...
透视数据!德州机器人代打脚本(... 透视数据!德州机器人代打脚本(透视)底牌透视挂辅助挂(可靠开挂辅助德州论坛)-哔哩哔哩;德州机器人代...
透视插件!wpk模拟器多开(透... 透视插件!wpk模拟器多开(透视)底牌透视挂辅助工具(可靠开挂辅助插件教程)-哔哩哔哩;1、透视插件...
透视玄学!hhpoker一直输... 透视玄学!hhpoker一直输有挂(透视)底牌透视挂辅助脚本(可靠开挂辅助德州教程)-哔哩哔哩是一款...
透视新版!德州局透视脚本(透视... 透视新版!德州局透视脚本(透视)底牌透视挂辅助app(可靠开挂辅助可靠教程)-哔哩哔哩;致您一封信;...
透视玄学!hhpoker辅助器... 透视玄学!hhpoker辅助器,情怀宜春辅助挂定制交易平台,辅助教程(有挂详细)-哔哩哔哩1、这是跨...