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

【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.xdnf.cn/news/17373.html

相关文章:

  • FMS 2025存储峰会获奖技术全景解读
  • C/C++基础详解(二)
  • AcWing 4579. 相遇问题
  • Day38 Dataset和Dataloader类
  • Datawhale AI夏令营-记录2
  • NVIDIA Jetson实战笔记
  • 【c++】探秘Loop机制:C++中优雅的双向数据交互模式
  • 力扣 hot100 Day70
  • 【Python 高频 API 速学 ⑥】
  • CrystalDiskInfo 9.0.1 安装教程 - 硬盘检测工具下载安装步骤详解
  • 基于迁移学习的伺服电机轴承故障诊断
  • Python变量引用拷贝
  • 求和算法的向后稳定性 backward stable
  • 大模型“涌现”背后的暗线——规模、数据、目标函数的三重协奏
  • Spring 的原理探究
  • 服务器硬件电路设计之I2C问答(二):I2C总线的传输速率与上拉电阻有什么关系?
  • vs2022编译Activemq
  • 创建一个django项目
  • 【js】判断异步函数的返回值要加await
  • 大语言模型提示工程与应用:大语言模型对抗性提示安全防御指南
  • springboot 2.4跨域变化和swagger结合的问题
  • orcad的操作(1)
  • BGP笔记
  • 微积分 | 外微分
  • vue+flask山西非遗文化遗产图谱可视化系统
  • 通过 SCP 和 LXD 配置迁移 CUDA 环境至共享(笔记)
  • AI编程工具 | Trae介绍
  • 智能的本质
  • 实数与复数及欧拉公式关系
  • 卷板矫平机:金属板材的“脊椎按摩师”