当前位置: 首页 > article >正文

C++泛型编程-函数模板、类模板

模板是一种参数化多态性的工具,可以为逻辑功能相同而类型不同的程序提供代码共享的机制,为什么需要模板呢,这主要是因为下面这一原因?

强类型设计语言中,参与运算的所有对象的类型在编译的时候便可确定下来,但同时有一些副作用,比如下面的代码

int max(int a,int b)
{return a>b?a:b;}
//和
int max(float a,float b)
{return a>b?a:b;}

两种均为求最大值,但是参数类型不同

强类型的程序设计迫使程序员为逻辑结构相同而具体类型不同的对象编写模式一致的代码,但是无法抽取其中的共性,不利于程序的维护。

1.函数模板

1.1定义

定义格式如下:

template<模板参数表>

<返回值类型><函数名>(<参数表>)

{

        <函数体>

}

其中:

关键字template是定义模板的关键字

<模板参数表>:包含一个或者多个用逗号分开的模板参数项,每一个有保留字class或者typename开始,后跟用户命名的标识符

1.2分类

模板函数主要分为普通模板函数和模板特化函数

代码如下:

#include "basic.h"
template<typename T1,typename T2>
void fun(T1 a, T2 b) {
	cout << "普通模板函数" << endl;
}

template<>
void fun<int, char>(int a, char b) {
	cout << "模板特化函数" << endl;
}
int main() {
	//以下调用普通模板函数
	fun(10, 10);
	fun("hello", 10);
	//下为模板特化函数
	fun(10, 'c');
	//显式指定模板参数
	fun<int, int>(10, 'b');
	return 0;
}

有以下三点需要注意:

1.模板特化优先级高:当参数类型完全匹配特化模板时,特化模板优先调用。
2.强制调用普通模板:如果希望调用普通模板,即使参数类型匹配特化模板,可以通过显式指定模板参数来实现:
3.避免歧义:如果模板重载和特化可能引发歧义,应尽量使用明确的调用方法或增加模板约束条件。

2.类模板

2.1定义

类是对一组对象的公共性质的抽象,而类模板则是对不同类的公共性质的抽象,因此类模板属于更高层次的抽象

格式如下:

template<模板参数表>

class<类模板名>

{

<类成员声明>

}

其中:

<模板参数表>包含一个或者多个用逗号分隔开的类型,参数项可以包含数据类型,也可以包含类属类型:如果是类属类型,需要加前缀class或者typename

注意:

类模板中的成员函数和重载的运算符必须为函数模板,它们的定义可以放在类模板的定义体中,与类中的成员函数的定义方法一致,也可以放在类模板的外部,则要采用以下的形式

template<模板参数表>

<返回值类型><类模板名><类型名表>::<函数名>(<参数表>)

{

<函数体>

}

2.2分类

对于类模板,主要有以下三类:全特化类 偏特化类  主版本模板类

代码如下:

template<typename T1,typename T2>
class Test {
public:
	Test(T1 i, T2 j) :a(i), b(j) {
		cout << "模板类" << endl;
	}
private:
	T1 a;
	T2 b;
};

template<>
class Test<int, char> {
public:
	Test(int i, char j) :a(i), b(j) {
		cout << "全特化" << endl;
	}
private:
	int a;
	char b;
};

template<typename T2>
class Test<char, T2> {
public:
	Test(char i, T2 j) :a(i), b(j) {
		cout << "偏特化" << endl;
	}
private:
	char a;
	T2 b;
};
int main() {
	Test<double, string> obj1(10.0, "hello");
	Test<int, char> obj2(10, 'b');
	Test<char, double> obj3('a', 10.99);
}

对主版本模板类、全特化类、偏特化类的调⽤优先级从⾼到低进⾏排序是:全特化类 > 偏特化类 > 主版本模板类


http://www.kler.cn/a/399308.html

相关文章:

  • nuget 管理全局包、缓存和临时文件夹
  • C++ 内联函数
  • PlantUML——时序图
  • 【STL】set,multiset,map,multimap的介绍以及使用
  • 实验8.1 无失真信源编码的实现
  • RabbitMQ实战启程:从原理到部署的全方位探索(上)
  • 使用Web Animations API实现复杂的网页动画效果
  • k8clone二进制工具迁移k8s中的无状态应用
  • 【汇编】c++游戏开发
  • Kubernetes 集群中防火墙配置的挑战及替代防护策略
  • 计算机网络基础(3)_应用层自定义协议与序列化
  • SQL面试题——抖音SQL面试题 主播播出时长
  • 【数据结构与算法】查找
  • Sping全面复习
  • Dijkstra 算法的实现方案
  • 蓝队基础之网络七层杀伤链
  • Linux解决普通用户无法使用sudo指令的问题
  • C++ 常函数、常对象
  • android framework ams/wms常见系统日志(main\system\events\crash,protoLog使用)
  • springmvc通过使用map来进行数据的接收和使用
  • 【python系列】python数据类型之字符串
  • uniapp h5 实现扫扫二维码
  • 排序算法 -快速排序
  • 【 LLM论文日更|检索增强:大型语言模型是强大的零样本检索器 】
  • Java基础-组件及事件处理(中)
  • 深度学习的艺术:揭秘卷积神经网络(CNN)的神秘面纱