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

【C++】模版进阶

本文是小编巩固自身而作,如有错误,欢迎指出!

一.非参数类型模版

(1)非参数类型模版的定义

 非参数类型模板(通常称为非类型模板参数)是 C++ 模板机制的一个重要特性,它允许在模板定义中使用常量表达式作为模板参数。也就是说模版参数也,可以不是类型而是值。

 (2)非参数类型模版应用

但是我们为什么要使用非类型参数模版呢?

我们先看看以下代码

#define N 10
template<class T>
class stack
{
private:T _a[N];int _top;int _capacity;
};
int main()
{stack<int> s1;//10stack<int> s2;//1000,单单使用宏N无法满足创建不同容量栈的需求
}

我们通过上述代码就可以发现,我们实现这个栈的时候我们单单使用一个宏N无法满足创建不同容量栈的需求,因此我们可以使用非参数类型模版

//使用非类型模版参数
template<class T=int,size_t N=100>
class stack2
{
private:T _a[N];int _top;int _capacity;
};

二.模板特化

(1)模版特化的定义

模板特化是C++模板编程中的一个重要特性,它允许针对特定的模板参数类型提供专门的实现版本。当我们使用模板时,模板会根据传入的参数生成相应的代码,但有时候对于某些特定的参数类型,我们希望有不同的处理逻辑,这时就可以使用模板特化。

(2)模版特化的应用

那么在什么场景下我们使用模版特化呢?我们看看以下代码

template<class T>
bool Less(const T& left, const T& right)//使用&避免传值传参,同时const修饰避免使用引用将原值修改
{return left < right;
}
//特化   
template<>
bool Less<double*>(double* const & left,double* const & right)//const 在*左边修饰指针指向对象,在*  w右边修饰指针本身
{return *left < *right;	
}
template<>
bool Less<string*>(string* const & left, string* const & right)
{return *left < *right;
}

在上述代码我们就可以发现一个问题,当我们这个比较函数比较的是int,char等类型是可以直接比较的,但是如果给定的类型是int*,string*等等,就会出现比较的是地址,而并非内容,因此,对其使用特殊化处理,也就是所谓的模版特化

(3)全特化与偏特化

3.1全特化

所谓全特化,就是将模版的每一个参数特殊化处理,而偏特化就是只处理部分参数

下面是全特化


template<class T1,class T2>
class Date
{
public:Date(){cout << "Date(T1,T2)" << endl;}
private:T1 d1;T2 d2;};
//全特化
template<>
class Date<int,char>
{
public:Date(){cout << "Date(int,char)" << endl;}
};

3.2偏特化

而偏特化就又要分为两类了,特化部分参数和对参数进一步限制

3.2.1特化部分参数
//偏特化
//特化部分参数
template<class T1>
class Date<T1,char>
{
public:Date(){cout << "Date(T1,char)" << endl;}
};
3.2.2对参数进一步限制
//偏特化
//对参数进一步限制
template<class T1,class T2>
class Date<T1*, T2*>
{
public:Date(){cout << "Date(T1*,T2*)" << endl;}
};template<class T1, class T2>
class Date<T1&, T2&>
{
public:Date(){cout << "Date(T1&,T2&)" << endl;}
};

三.模版分离编译

(1)分离编译常见的报错原因

当模板的声明和定义分离:即声明在.h文件,但是定义在.cpp文件的时候,往往会产生链接错误。因为链接时,需要通过重定位,将所遇到的标识符(如某个函数名)的地址链接上。

即如图所示

我们会发现报错了,原因是什么呢?,其实原因就在于在进行链接的时候,编译器没有没有找到实例化模版,无法对不确定的类型(上图的T)进行链接,因此无法运行。

(2)分离编译无法运行的解决方法

那我们该如何解决上述问题呢,这里提供两种思路一种是显式实例化,一种是就是直接将定义写到头文件了

2.1显示实例化
//.h
template<class T>
void funcA(const T& x);
//.cpp
template<class T>
void funcA(const T& x)
{cout << "void FuncT(const T& x)" << endl;
}
template
void funcA(const int& x);
2.2声明和定义一起放在头文件
template<class T>
void funcA(const T& x)
{cout << "void FuncT(const T& x)" << endl;
}

本次分享就到这里结束了,后续会继续更新,感谢阅读!

http://www.dtcms.com/a/323471.html

相关文章:

  • redis存储原理与数据模型
  • 复数与频谱的联系
  • 库函数蜂鸣器的使用(STC8)
  • ECML PKDD 2025 | 时间序列(Time Series)论文总结
  • “秦时明月”提前布局商标被电视剧侵权!
  • 深入理解 RedisTemplate:简化 Java 与 Redis 的交互!
  • 【系统编程】进程创建
  • 本地进行语音文字互转
  • 国内外大模型体验与评测
  • Vue2 字段值映射通用方法
  • Python 属性描述符(描述符用法建议)
  • 基于Prometheus、Grafana、Loki与Tempo的统一监控平台故障排查与解决方案
  • redis开启局域网访问
  • C++讲解---通过转换函数和运算符函数直接调用类的对象
  • Horse3D引擎研发笔记(三):使用QtOpenGL的Shader编程绘制彩色三角形
  • Aurora设计注意问题
  • 【递归、搜索和回溯】FloodFill 算法介绍及相关例题
  • 11. 为什么要用static关键字
  • 香橙派 RK3588 部署千问大模型 Qwen2-VL-2B 多轮交互式对话
  • 【工具】Python多环境管理
  • ubuntu安装ollama流程
  • Day 8: 深度学习综合实战与进阶技术 - 从优化到部署的完整流程
  • Java+Vue打造的采购招投标一体化管理系统,涵盖招标、投标、开标、评标全流程,功能完备,附完整可二次开发的源码
  • 数据结构day06
  • 102-基于Spark的招聘数据预测分析推荐系统
  • 物质和暗物质形成机制
  • 【排序算法】④堆排序
  • 工具箱许愿墙项目发布
  • AI_RAG
  • 复现论文关于3-RPRU并联机器人运动学建模与参数优化设计