C++系列-模版

🌈个人主页:羽晨同学 

💫个人格言:“成为自己未来的主人~”  

非类型模版参数

模板参数分类型模板参数与非类型模板参数

类型形参即:出现在模板参数列表,跟在class或者typename之类的参数类型名称

非类型形参即:就是用一个常量作为类(函数)模版的一个参数,在类(函数)模版中可将该参数当成常量来使用

int main()
{Stack<int> st1;     //10Stack<int,100> st1;     //100Stack<int,1000> st1;     //1000return 0;
}

首先,我们想在定义的类中实现这样的功能,很明显,这是不可能的,但是有了非类型模板参数之后,这就成为了可能,那应该怎么做呢?

#define _CRT_SECURE_NO_WARNINGS 
#include<stack>
#include<iostream>
using namespace std;
template<class T,size_t N=10>
class Stack
{
public:void func(){N++;}
private:int _a[N];int _top;
};
int main()
{Stack<int> st1;     //10Stack<int,100> st1;     //100Stack<int,1000> st1;     //1000return 0;
}

你看, 这样的话,我们就可以通过改变传递的参数来改变N的值

需要注意的是,C++20之前,浮点数是不允许作为非类型模版参数的

但是在C++20当中,它是可以的。

template<double X,int*ptr>
class A
{};

但是类对象和字符串是不允许的

 array

array相较于vector而言,其实它具备更严格的越界检查。

#include<array>
#include<vector>
int main()
{//严格越界检查array<int, 10> aa1;cout << sizeof(aa1) << endl;aa1[10];aa1[14] = 1;array不如用vector。鸡肋的设计//vector<int> v1(10, 1);//v1[14];//cout << sizeof(v1) << endl;return 0;
}

这里其实就体现出来了一部分array的特征

	int aa2[10];aa2[13];

你看,在这个代码中,就不会进行报错的,这是因为在静态变量中, 执行的是随机抽样检测,所以后面是不会报错的。

我们再来看一下vector的越界部分,在vector当中,同样也会进行严格的越界检查,溢出也会进行报错。

但是,array所花费的内存比vector更大:

所以说,其实array是完全鸡肋的设计

你看,下面的这段代码是我们所实现的一个打印int的打印函数

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

在这个代码中,我们所能打印的只是int类型的变量,但是我们想要打印其他的类型,我们应该怎么做呢,最简单的,引入模版的概念。

 我们来看下面的这一段代码:

template<class T>
void PrintVector(const vector<T>& v)
{vector<T>::const_iterator it = v.begin();while (it != v.end()){cout << *it << endl;++it;}cout << endl;
}
int main()
{vector<double> v2{1.1, 2.2, 1.3, 6.6, 7.7, 8.8};PrintVector(v2);return 0;
}

但是很抱歉的是,这样代码是会进行报错的,这是为什么呢?

这是因为类模板在没有实例化之前,是不会去里面查具体的东西的,这就导致了编译器不知道这个是vector<T>::const_iterator it类型还是变量 。

 而在这个时候,我们就会在代码的前面加一个typename来告诉编译器这是一个类型

template<class T>
void PrintVector(const vector<T>& v)
{typename vector<T>::const_iterator it = v.begin();while (it != v.end()){cout << *it << endl;++it;}cout << endl;
}
int main()
{vector<double> v2{1.1, 2.2, 1.3, 6.6, 7.7, 8.8};PrintVector(v2);return 0;
}

特化

接下来,让我们看一下要实现的比较日期类的函数

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}bool operator<(const Date& d)const{return (_year < d._year) ||(_year == d._year && _month < d._month) ||(_year == d._year && _month == d._month && _day < d._day);}bool operator>(const Date& d)const{return (_year > d._year) ||(_year == d._year && _month > d._month) ||(_year == d._year && _month == d._month && _day > d._day);}friend ostream& operator<<(ostream& _cout, const Date& d);
private:int _year;int _month;int _day;
};ostream& operator<<(ostream& _cout, const Date& d)
{_cout << d._year << "-" << d._month << "-" << d._day;return _cout;
}
//template<class T>
//bool Less(const T& left, const T& right)
//{
//	return left < right;
//}
bool Less(Date* left, Date* right)
{return *left < *right;
}

你看,在这段代码中,我们实现了一个小于的比较,这里能够实现是因为我们对这个<进行的函数重载。

通常情况下,我们使用模版可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果,需要特殊化处理。

template<class T>
bool Less( T left,  T right)
{return left < right;
}
int main()
{cout << Less(1, 2) << endl;Date d1(2022, 7, 7);Date d2(2022, 6, 8);cout << Less(d1, d2) << endl;Date* p1 = &d1;Date* p2 = &d2;cout << Less(p1, p2) << endl;return 0;
}

 在这个代码当中:

我们可以看到,第三个答案是错误的。因为这个是地址的比较

此时,我们就需要对模版进行特化,即:在原模板基础上,针对特殊类型进行特殊化的处理方式。模板特化中,分为类模板特化和函数模板特化

//类模板
template<class T1,class T2>
class Data
{
public:Data(){cout << "Data<T1,T2>-原模板" << endl;}
private:T1 _d1;T2 _d2;
};
//特化:针对某种特殊类型,进行特殊化处理
//全特化
template<>
class Data<int,char>
{
public:Data(){cout << "class Data<int,char>-> 全特化 " << endl;}
};
template<class T1>
class Data<T1, int>
{
public:Data(){cout << "class Data<T1, int>->半特化" << endl;}
private:T1 _d1;int _d2;
};

上面的这个其实给出了全特化和半特化的例子,半特化中我们引出了参数,一个固定,一个随机参数。 

限定模版类型

// 限定模版的类型
template <typename T1, typename T2>
class Data <T1*, T2*>
{
public:Data() { cout << typeid(T1).name() << endl;cout << typeid(T2).name() << endl;cout << "Data<T1*, T2*>-偏特化" << endl << endl;//T1 x1;//T1* p1;}
};template <typename T1, typename T2>
class Data <T1&, T2&>
{
public:Data(){cout << typeid(T1).name() << endl;cout << typeid(T2).name() << endl;cout << "Data<T1&, T2&>" << endl << endl;}
private:
};template <typename T1, typename T2>
class Data <T1&, T2*>
{
public:Data(){cout << typeid(T1).name() << endl;cout << typeid(T2).name() << endl;cout << "Data<T1&, T2*>" << endl << endl;}
private:
};

好了,本次的文章就到这里了,我们下次再见。  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/431997.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot 数据库表结构文档生成

官方地址&#xff1a;https://github.com/pingfangushi/screw screw 螺丝钉&#xff0c;支持以下数据库 MySQL MariaDB TIDB Oracle SqlServer PostgreSQL Cache DB&#xff08;2016&#xff09; 生产文档支持 html word markdown 开始 添加依赖 <!-- 螺丝钉 --><…

软件测试技术之 GPU 单元测试是什么!

1 背景 测试是开发的一个非常重要的方面&#xff0c;可以在很大程度上决定一个应用程序的命运。良好的测试可以在早期捕获导致应用程序崩溃的问题&#xff0c;但较差的测试往往总是导致故障和停机。 单元测试用于测试各个代码组件&#xff0c;并确保代码按照预期的方式工作。单…

三维重建的几何评价指标

1.三维重建的几何评价指标 1.1 Chamfer Distance Geometry quality (1) Chamfer Distance&#xff08;CD&#xff09; CD衡量两组点云之间的几何差异&#xff0c;距离越小越好。 CD是一种用于衡量两个点云之间相似度的常用几何评价指标。它计算一个点云中每个点到另一个点云的…

seL4 Threads(四)

官网链接: Threads Threads 这篇教程主要是使用seL4中的threads。 TCB Thread Control Blocks seL4提供了线程代表执行的上下文以及管理处理器时间。seL4中的线程是通过线程控制块对象&#xff08;TCB&#xff09;实现的&#xff0c;每个内核线程都有一个线程控制块。 线程…

Web3技术在元宇宙中的应用:从区块链到智能合约

随着元宇宙的兴起&#xff0c;Web3技术正逐渐成为其基础&#xff0c;推动着数字空间的重塑。元宇宙不仅是一个虚拟世界&#xff0c;它还代表着一个由去中心化技术驱动的新生态系统。在这个系统中&#xff0c;区块链和智能合约发挥着至关重要的作用&#xff0c;为用户提供安全、…

Vue | watch监听

Vue | watch监听 在Vue.js的世界里&#xff0c;watch监听器是一个强大且灵活的工具&#xff0c;它允许我们在数据变化时执行特定的逻辑。本文将深入探讨watch的出现背景、使用方法、应用场景、源码原理以及扩展技巧&#xff0c;旨在帮助读者全面掌握这一重要特性。 文章目录 Vu…

TMStarget学习——T1 Segmentation数据处理及解bug

最新学习季公俊老师的神器 TMStarget 的第一个模块基于结构像的靶区计算T1 segmentation。下面上步骤&#xff1a; (1)在github 上下载 TMStarget https://github.com/jigongjun/Neuroimaging-and-Neuromodulation (2)按照要求下载依赖工具软件AFQ、vistasoft、SPM12 &#…

笔试编程-百战成神——Day02

1.简写单词 题目来源&#xff1a; 简写单词——牛客网 测试用例 算法原理 本题的主要难点就是如何识别每一个单词并且返回其首字母大写&#xff0c;最终组成一个新的字符串后输出&#xff0c;这里我们使用while(cin>>str)就可以解决&#xff0c;直接忽略每一个空格直接…

20240926 每日AI必读资讯

一个开源的自托管 AI 入门工具包 - 此工具包利用Docker Compose模板&#xff0c;包含多种本地AI工具并提供AI工作流模板和网络配置&#xff0c;简化了本地AI工具的安装和使用。 安装它将拥有&#xff1a; • 一个拥有 400 多个 AI 组件和集成的低代码平台 • Ollama&#xf…

基于stm32物联网身体健康检测系统

在当今社会&#xff0c;由于经济的发展带来了人们生活水平不断提高&#xff0c;但是人们的健康问题却越来越突出了&#xff0c;各种各样的亚健康随处可在&#xff0c;失眠、抑郁、焦虑症&#xff0c;高血压、高血糖等等侵袭着人们的健康&#xff0c;人们对健康的关注达到了一个…

单细胞Scanpy流程学习和整理(单样本10X数据读取/过滤/降维/聚类)

打算仔细学习一下基于python的单细胞相关分析框架hhh 新手上路写的很繁琐&#xff0c;多多包涵&#xff0c;本次用的IDE是Visual studio code。 流程来自Scanpy官网(Preprocessing and clustering 3k PBMCs (legacy workflow))&#xff1a; https://scanpy.readthedocs.io/e…

01【MATLAB】最小二乘系统辨识

目录 1.系统辨识的定义及其分类 1.1 系统辨识的定义 1.2 系统辨识的分类 2.参数模型 3.系统辨识的步骤 一、最小二乘法&#xff08;Least Squares Method&#xff09;一般步骤 二、LSM原理及应用 三、LSM在控制系统建模中的应用 1.系统辨识的定义及其分类 1.1 系统辨识的…

力扣P1706全排列问题 很好的引入暴力 递归 回溯 dfs

代码思路是受一个洛谷题解里面大佬的启发。应该算是一个dfs和回溯的入门题目&#xff0c;很好的入门题目了下面我会先给我原题解思路我想可以很快了解这个思路。下面是我自己根据力扣大佬写的。 我会进行详细讲解并配上图辅助理解大家请往下看 #include<iostream> #inc…

【机器学习】Flux.jl 生态

官方API https://fluxml.ai/Flux.jl/stable/ecosystem/ 官网给出了 Flux’s model-zoo&#xff0c; 是一个庞大的案例库&#xff0c; 可以提供直观的参考&#xff0c; 并且还列举了基于 Flux.jl 开发的第三方库。 机器视觉 ObjectDetector.jl YOLO 抓取的“预备跑” 图像Met…

使用vite+react+ts+Ant Design开发后台管理项目(一)

前言 本文将引导开发者从零基础开始&#xff0c;运用vite、react、react-router、react-redux、Ant Design、less、tailwindcss、axios等前沿技术栈&#xff0c;构建一个高效、响应式的后台管理系统。通过详细的步骤和实践指导&#xff0c;文章旨在为开发者揭示如何利用这些技…

SpringCloud Alibaba之Seata处理分布式事务

&#xff08;学习笔记&#xff0c;必用必考&#xff09; 问题&#xff1a;Transactional 的9种失效场景&#xff1f; 1、介绍 1.1、简介 官网地址&#xff1a;Apache Seata 源码地址&#xff1a;Releases apache/incubator-seata GitHub Seata是一款开源的分布式事务解决…

Thinkphp5x远程命令执行 靶场攻略

环境配置 靶场&#xff1a;vulhub/thinkphp/5-rce docker-compose up -d #启动环境 漏洞复现 1.访问靶场&#xff1a;http://172.16.1.198:8080/ 2.远程命令执⾏ POC&#xff1a; ?sindex/think\app/invokefunction&functioncall_user_func_array&vars[0]system…

【VUE_ruoyi-vue】基于ruoyi-vue框架实现简单的系统通用文件模块

基于ruoyi-vue框架&#xff0c;新增一个简单的系统通用文件模块&#xff0c;服务与各个模块涉及到文件上传信息的记录和相关展示 运行sql,创建数据库表 DROP TABLE IF EXISTS sys_file_info; CREATE TABLE sys_file_info (id int(11) NOT NULL AUTO_INCREMENT COMMENT id,lin…

在虚幻引擎中实时显示帧率

引擎自带了显示帧率的功能 但是只能在编辑器中显示 , 在游戏发布后就没有了 , 所以我们要自己做一个 创建一个控件蓝图 创建画布和文本 , 修改文本 文本绑定函数 , 点击创建绑定 添加一个名为 FPS 的变量 格式化文本 用大括号把变量包起来 {FPS Int} FPS 然后转到事件图表…

机器学习算法与Python实战 | 三万字详解!GPT-5:你需要知道的一切(下)建议收藏!

本文来源公众号“机器学习算法与Python实战”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;三万字详解&#xff01;GPT-5&#xff1a;你需要知道的一切 作者&#xff1a;Alberto Romero &#xff08;青稞AI整理&#xff09; 原…