C++_21_模板

模板

简介:

一种用于实现通用编程的机制。
通过使用模板我们可以编写可复用的代码,可以适用于多种数据类型。
C++模板的语法使用角括号 < > 来表示泛型类型,并使用关键字 template 来定义和声明模板

概念:

c++范式编程

特点:

  • 可以将数据类型作为参数进行传递

模板引入:

#include <iostream>
using namespace std;
// 模板的引入
//   想打印任何接收的类型 就得写所有类型的函数进行接收
void print(char a)
{cout<<a<<endl;
}
void print(int a)
{cout<<a<<endl;
}
void print(double a)
{cout<<a <<endl;
}int main(int argc, char const *argv[])
{print('a');print(1);return 0;
}

模板的使用:

#include <iostream>
using namespace std;
template<class z>
//模板的定义 自己会推导你写入的是什么 将a的类型换成什么
void print(z a)
{cout<< a <<endl;
}
int main(int argc, char const *argv[])
{print('a');print(10);print("你好");return 0;
}

在这里插入图片描述

模板函数:

语法:

template <class 假设的类型1 ,class 假设的类型2...>返回值类型 函数名(形参列表)
{函数体;
}

注意:

当前函数中任何一处使用数据类型的地方都可以使用假设的类型

例子:

在这里插入图片描述

特点:

  • 1 函数模板可以自动推导参数的类型,但是不会进行类型转换
  • 2 函数模板可以自动类型推导,也可以显式指定类型
    • 显式指定类型
      • 函数名<指定的类型1,指定的类型2,…>(实参列表);
  • 3,只能在声明的所在函数中使用

补充:

函数模板会编译两次:

1,在加载时对函数模板进行第一次编译

2,在调用时推导T的类型再次将函数模板编译为模板函数

模板函数与普通函数的区别

  • 1,函数模板不允许自动类型转化 普通函数能够自动进行类型转
  • 2,函数模板和普通函数同时识别,优先使用普通函数,加<>强制使用函数模板
  • 3,函数模板可以使用<>,普通函数不行

模板函数 局限性:

#include <iostream>
using namespace std;
//                  函数模板的局限性
template <class T>
void method(T t)
{cout << t << endl;
}
class A
{
};
int main(int argc, char const *argv[])
{method(10);A a;method(a); // 此时模板可以推导出T的类型为A,但是A类没有重载<<运算符,所以// 无法通过cout输出, 此时语法无错, 但是无法编译生成可执行文件 return 0;
}解决方案1 : 重载 << 运算符
#include <iostream>using namespace std;
template <class T>
void method(T t)
{cout << t << endl;
}
class A
{
};
ostream &operator<<(ostream &out, A &a)
{out << "打印A的对象" << endl;return out;
}
int main(int argc, char const *argv[])
{method(10);A a;method(a);return 0;
}
解决方案2 : 指定模版函数
#include <iostream>using namespace std;
template <class T>
void method(T t)
{cout << t << endl;
}
class A
{
};
// 指定模版函数
template <>
void method<A>(A a)
{cout << "打印A的对象" << endl;
}
int main(int argc, char const *argv[])
{method(10);A a;method(a);return 0;
}

类模板

概念:

  • 有模板的类

语法:

template<class 假设的类型1,class 假设的类型2....>
{}

作用:

当前类中任何一处使用数据类型的地方都可以使用假设的类型

创建对象

类名 <类型1,类型2...> 对象名(实参列表);
类名 <类型1,类型2...> *对象名 = new类名<类型1,类型2>(实参列表)

模板类作为父类

  • 方案1 子类指明父类模板类型
  • 方案2 子类也是模板类

在这里插入图片描述

模板类的函数声明与实现分离

注意:

  • 每一个 类外实现的函数都是模板函数
 template <class 假设的类型>返回值类型 类名<><假设的类型>::函数名(形参列表){ }
#include <iostream>
using namespace std;
template <class Q>
class Data
{
private:Q q;public:Data();Data(Q q);Q getQ();void setQ(Q q);
};
template <class X>
Data<X>::Data()
{
}
template <class Q>
Data<Q>::Data(Q q)
{this->q = q;
}
template <class Q>
Q Data<Q>::getQ()
{return q;
}
template <class Q>
void Data<Q>::setQ(Q q)
{this->q = q;
}
int main(int argc, char const *argv[])
{Data<int> data(10);return 0;
}

hpp文件

因为模板类的声明与实现无法分离,故将模板类的声明与实现在同一文件中。该文件的后缀名为 .hpp

示例:

在这里插入图片描述

  • data.hpp
template <class Q>
class Data
{
private:Q q;public:Data();Data(Q q);Q getQ();void setQ(Q q);
};
template <class X>
Data<X>::Data()
{
}
template <class Q>
Data<Q>::Data(Q q)
{this->q = q;
}
template <class Q>
Q Data<Q>::getQ()
{return q;
}
template <class Q>
void Data<Q>::setQ(Q q)
{this->q = q;
}

main.cpp

#include <iostream>
#include "data.hpp"
using namespace std;
int main(int argc, char const *argv[])
{Data<int> data(10);return 0;
}

编译命令

g++ main.cpp

类模板对象作为形参

#include <iostream>
#include "../15_code/data.hpp"
using namespace std;
// 指明类型
// void print(Data<int>& data)
// {
// cout << "xxx" << endl;
// }
// void print(Data<char>& data)
// {
// cout << "YYY" << endl;
// }
// 函数模板
template <class E>
void print(Data<E> &data)
{cout << "xxx" << endl;}
int main(int argc, char const *argv[])
{Data<int> data(10);print(data);Data<char> data02('A');print(data02);return 0;
}

自定义集合

作用:

存储一组数据类型相同的数据的容器

特点

可以存储任何一种数据类型 基本类型和自定义类型

#include "array.hpp"
class Person
{
private:char *name;public:Person(){this->name = NULL;}Person(char *name){// 测试存储效果cout << name << "被创建" << endl;int len = strlen(name);this->name = (char *)calloc(len + 1, 1);strcpy(this->name, name);}Person(const Person &pe){// if (name != NULL)// {//     // free(name);  有时候会是野指针 释放野指针就崩了//     name = NULL;// }int len = strlen(pe.name);this->name = (char *)calloc(len + 1, 1);strcpy(this->name, pe.name);}// 析构~Person(){cout << name << "被释放了" << endl;} // 不用释放因为  头中已经释放过了char *getName(){return name;}
};
int main(int argc, char const *argv[])
{// 实验基本数据类型  char sort int float double long bool// 实验存 intArrayList<int> nums;cout << "实验 int 型" << endl;nums.add(1);nums.add(2);nums.add(3);nums.add(4);nums.add(5);for (int i = 0; i < nums.getlen(); i++){cout << nums.get(i) << endl; // 按下标获取}// 实验存 char 型ArrayList<char> cs;cs.add('A');cs.add('b');cs.add('c');cs.add('d');cs.add(65);cout << "实验 char 型" << endl;for (int i = 0; i < cs.getlen(); i++){cout << cs.get(i) << endl; // 按下标获取}// 实验long型ArrayList<long> lo;lo.add(123123123L);cout << "实验 long 型" << endl;for (int i = 0; i < lo.getlen(); i++){cout << lo.get(i) << endl; // 按下标获取}// 测试bool型ArrayList<bool> bol;bol.add(true);bol.add(false);cout << "实验 bool 型" << endl;for (int i = 0; i < bol.getlen(); i++){cout << bol.get(i) << endl; // 按下标获取}// 测试string型ArrayList<string> str;str.add("铁锤打铁");str.add("云边有个小卖部");cout << "实验 bool 型" << endl;for (int i = 0; i < str.getlen(); i++){cout << str.get(i) << endl; // 按下标获取}cout<<"\n"<<endl;//  测试自定义类型ArrayList<Person> ps;ps.add(Person("哇嘎"));ps.add(Person("铁头"));ps.add(Person("铁锤"));cout << "\n";cout << "遍历后的结果" << endl;for (int i = 0; i < ps.getlen(); i++){cout << ps.get(i).getName() << endl;}return 0;
}

类型转换

1, C提供的强制转换

语法:(转换后的类型)要转换的数据或变量

2,静态转换

语法:

//基本类型转换 支持
int num = static_cast<int>(3.14f);
//基本指针类型转换 不支持
float f=0.0f;
//int *p1 = static_cast<int *>(&f);
//上行转换 支持(安全)
Base *p2 = static_cast<Base *>(new Son);
//下行转换 支持(不安全)
Son *p3 = static_cast<Son *>(new Base);
//不相关类型转换 不支持
//Son *p4 = static_cast<Son *>(new Other);

3,动态类型转换

语法:

dynamic_cast<T> (要转换的数据)

示例

//基本类型转换 不支持
//int num = dynamic_cast<int>(3.14f);
//基本指针类型转换 不支持
float f=0.0f;
//int *p1 = dynamic_cast<int *>(&f);
//上行转换 支持(安全)
Base *p2 = dynamic_cast<Base *>(new Son);
//下行转换 不支持(不安全)
//Son *p3 = dynamic_cast<Son *>(new Base);
//不相关类型转换 不支持
//Son *p4 = dynamic_cast<Son *>(new Other);

4,常量转换

语法 : **const_cast **

注意:只能对指针与引用的变量使用

示例

//将非const 转换成 const
int num = 10;
const int *p1 = const_cast<const int *>(&num);
//将const 转换成 非const
const int data=0;
int *p = const_cast<int *>(&data);

5,重新解释转换

简介

这是最不安全的一种转换机制,最有可能出问题。
主要用于将一种数据类型从一种类型转换为另一种类型。它可以将一个指针转换成一个整数,也可以将一个整数转换成一个指针

语法

reinterpret_cast<T>

示例

//基本类型转换 不支持
//int num = reinterpret_cast<int>(3.14f);
//基本指针类型转换 支持
float f=0.0f;
int *p1 = reinterpret_cast<int *>(&f);
//上行转换 支持(安全)
Base *p2 = reinterpret_cast<Base *>(new Son);
//下行转换 支持(不安全)
Son *p3 = reinterpret_cast<Son *>(new Base);
//不相关类型转换 支持
Son *p4 = reinterpret_cast<Son *>(new Other);

总结:

1,强制转换
2,系统提供的函数进行转换静态转换基本类型 支持子转父 支持父转子 支持不相干 不支持动态转换基本类型 不支持子转父 支持父转子 不支持不相干 不支持常量转换常量转非常量非常量转常量重新解释基本类型 不支持子转父 支持父转子 支持不相干 支持

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Telephony VOWIFI

1、VOWIFI框架 参考3GPP 23402文档, VOWIFI有如下相关架构设置。 1、S2a信任的WIFI热点 2、S2b非信任WIF热点 3、S2c直联核心WIF热点 目前使用比较多的为S2b非信任WIF热点。 2、EPDG建立过程 //Telephony Log IWLAN拨号 08-30 21:36:34.702857 1347 5131 D ConnectivityS…

基于YOLOv5的教室人数检测统计系统

基于YOLOv5的教室人数检测统计系统可以有效地用于监控教室内的学生数量&#xff0c;适用于多种应用场景&#xff0c;比如 自动考勤、安全监控或空间利用分析 以下是如何构建这样一个系统的概述&#xff0c;包括环境准备、数据集创建、模型训练以及如何处理不同类型的媒体输入…

排序----希尔排序

void ShellSort(int* a, int n) {int gap n;while (gap > 1){// 1保证最后一个gap一定是1// gap > 1时是预排序// gap 1时是插入排序gap gap / 3 1;for (size_t i 0; i < n - gap; i){int end i;int tmp a[end gap];while (end > 0){if (tmp < a[end]){…

Linux——K8s集群部署过程

&#xff11;、环境准备 &#xff08;1&#xff09;配置好网络ip和主机名 control: node1: node2: 配置ip 主机名的过程省略 配置一个简单的基于hosts文件的名称解析 [rootnode1 ~]# vim /etc/hosts // 文件中新增以下三行 192.168.110.10 control 192.168.110.11 node1 1…

【redis-01】redis基本数据类型和使用场景

redis系列整体栏目 内容链接地址【一】redis基本数据类型和使用场景https://zhenghuisheng.blog.csdn.net/article/details/142406325 redis基本数据类型和使用场景 一&#xff0c;redis基本数据类型和使用场景1&#xff0c;String数据类型2&#xff0c;Hash数据类型3&#xff…

mat工具的几个实用地方

背景 使用mat的过程中&#xff0c;有几个值得关注的注意点&#xff0c;可以帮助我们尽快查找到问题的答案 mat实用的注意点 一.打开直方图后排序&#xff0c;直观查看内存占用大小,如下图所示 二.查看某个对象实例的具体值&#xff0c;点击对象&#xff0c;点击List Object…

vulnhub靶场 DC-3

地址: https://download.vulnhub.com/dc/DC-3-2.zip 开启NAT模式 namp只扫到了一个端口 打开网页有一个登录的页面 目录扫描一下,可以找到一个 后台登录界面 看一下指纹信息 joomla cms 网上搜一下可以发现存在一个JoomScan工具 在kali上面安装一下 apt install joomscan …

CSP-J2024全真模拟题 阅读程序题3+程序填空题

由于明天考试&#xff0c;今天晚上给大家提供详细的答案和解析&#xff0c;求关注点赞和评论 28.将第 1 行改为 &#xff03;include<iostream>&#xff0c;程序的运行结果不变。&#xff08;&#xff09; A.对B.错 29.本程序用到了队列而不是栈的思想。&#xff08;&a…

大数据新视界 --大数据大厂之算法在大数据中的核心作用:提升效率与智能决策

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

缓存装饰器@cached_property

这个装饰器好像在好多包里都有&#xff0c;我在阅读源码的过程中&#xff0c;transformers.utils也有这个。查阅资料&#xff0c;大体上了解了它的用法。参考&#xff1a;[python]cached_property缓存装饰器 - faithfu - 博客园 这个装饰器用在类里面的某个方法前面&#xff0…

7个提升网站分页体验的 CSS 和 JavaScript 代码片段

文章目录 前言正文1.简洁直观的悬停分页效果2.实时显示页码的分页3.适合响应式设计的多功能分页4.专为移动设备优化的分页5.无数字的极简分页设计6.触屏友好的分页7.结合无限滚动与分页的设计 总结 前言 分页是内容丰富的网站中不可缺少的导航工具&#xff0c;能帮助用户更轻松…

C++_CH18_构造函数与析构函数

C_CH18_构造函数与析构函数 1 类的默认成员函数 在编写类的时候&#xff0c;C编译器会默认生成6个默认的函数&#xff0c;但是不显示出来&#xff1a; 需要关注以下两个方面: 第一:我们不写时&#xff0c;编译器默认生成的函数行为是什么&#xff0c;是否满足我们的需求。 …

Java流程控制语句——条件控制语句详解(附有流程图)#Java条件控制语句有哪些?#if-else、switch

在 Java 编程中&#xff0c;条件控制语句用于控制程序的执行路径&#xff0c;决定根据某些条件来选择执行某段代码或跳过某段代码。它们是 Java 编程的重要组成部分&#xff0c;帮助开发者根据不同的输入、状态或数据流来编写更加灵活和动态的代码。在本文中&#xff0c;我们将…

【省时省力】告别 Node.js 安装配置的繁琐!国内镜像源加速,版本切换轻松搞定

前言 最近电脑开发环境又意外出现了异常,每次更新系统都是冒着很大的风险,这次最直接的影响就是一些基于nodejs的前端项目. 不同项目的版本环境要求不一致,最新的nodejs并不总是满足项目要求,因此为了重新部署自己开发的以及别人开发的项目,需要根据项目随时切换到相应的版本.…

线性系统分析

一、定义 (1)叠加性 若 且 则称该系统具有叠加性。 叠加性:系统的一个输入不影响系统对其他输入的响应。 (2)均匀性 若 对任意常数a下式都成立 则称该系统具有均匀性。 均匀性:系统能够保持对输入信号的缩放因子不变。 (3)线性系统 若一个系统同时具有叠加性和…

手把手教你-MAC虚拟环境搭建TensorFlow开发环境

参考如下代码布置&#xff0c;直接运行&#xff0c;即可: 1) 安装virtualenv $ sudo pip install virtualenv 2&#xff09;创建虚拟环境文件夹 $ virtualenv --system-site-packages -p python2.7 ./EnvPy27 3) 激活环境 $ source EnvPy27/bin/activate 4) 更新pip $ pi…

基于机器学习的癌症数据分析与预测系统实现,有三种算法,bootstrap前端+flask

研究背景 癌症作为全球范围内最主要的死亡原因之一&#xff0c;已成为当代医学研究和公共健康的重大挑战。据世界卫生组织&#xff08;WHO&#xff09;的统计&#xff0c;癌症每年导致全球数百万人的死亡。随着人口老龄化、环境污染和生活方式的改变&#xff0c;癌症的发病率逐…

如何联系真正的开发者而非公司??

&#x1f3c6;本文收录于《全栈Bug调优(实战版)》专栏&#xff0c;主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&am…

同态加密明文矩阵乘密文向量优化:BSGS小步大步法

摘要 本文介绍如何使用小步大步&#xff08;Baby-Step-Giant-Step&#xff0c;BSGS&#xff09;优化RLWE同态加密的明文矩阵和密文向量的乘法。使用 n n n\times n nn明文矩阵的对角打包和BSGS&#xff0c;可以将密文旋转的次数降低为 O ( n ) O(\sqrt{n}) O(n ​). 明文运算…

Vue3中el-table组件实现分页,多选以及回显

el-table组件实现分页&#xff0c;多选以及回显 需求思路1、实现分页多选并保存上一页的选择2、记录当前选择的数据3、默认数据的回显 完整代码 需求 使用 dialog 显示 table&#xff0c;同时关闭时销毁el-table 表格多选回显已选择的表格数据&#xff0c;分页来回切换依然正确…