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.mzph.cn/web/53256.shtml

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

相关文章

海外大带宽服务器连接失败怎么办?

在全球化日益加深的今天&#xff0c;海外大带宽服务器已成为企业拓展国际市场、提升业务效率的重要工具。然而&#xff0c;面对复杂多变的网络环境和技术挑战&#xff0c;服务器连接失败的问题时有发生&#xff0c;这不仅影响了企业的正常运营&#xff0c;还可能带来经济损失和…

如何写一个自动化Linux脚本去进行等保测试--引言

#我的师兄喜欢给我的休闲实习生活加活&#xff0c;说是让我在实习期间写一个自动化脚本去进行等保测试。呵呵哒。 怎么办呢&#xff0c;师兄的指令得完成&#xff0c;师兄说让我使用Python完成任务。 设想如下&#xff1a; 1、将Linux指令嵌入到python脚本中 2、调试跑通 …

【简历】25届河南某一本JAVA简历:从头到尾都表现的不懂技术

注&#xff1a;为保证用户信息安全&#xff0c;姓名和学校等信息已经进行同层次变更&#xff0c;内容部分细节也进行了部分隐藏 简历总体说明 今天看一份河南某重点一本大学的Java简历。 校招备战第一法则&#xff1a;必须确定自己的求职层次&#xff0c;是大厂、中厂还是小…

php语言基本语法

HP&#xff08;Hypertext Preprocessor&#xff09;是一种广泛使用的开源服务器端脚本语言&#xff0c;特别适合于Web开发。 它能够嵌入到HTML中&#xff0c;执行动态网页内容。 PHP的一些基本语法元素&#xff1a; 1. 基本结构 PHP代码通常嵌入到HTML中&#xff0c;以<…

OpenHarmony(鸿蒙南向开发)——小型系统芯片移植指南(二)

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ OpenHarmony&#xff08;鸿蒙南向开发&#xff09;——轻量系统芯片移植指南(一) Op…

基于深度学习的图像分类或识别系统(含全套项目+PyQt5界面)

目录 一、项目界面 二、代码实现 1、数据集结构 2、设置需要模型的训练参数和指定数据集路径 3、网络代码 4、训练代码 5、评估代码 6、结果显示 三、项目代码 一、项目界面 二、代码实现 1、数据集结构 每一个文件夹对应一个类别的数据 2、设置需要模型的训练参数和…

09.20 C++对C的扩充以及C++中的封装、SeqList

SeqList.h #ifndef SEQLIST_H #define SEQLIST_H#include <iostream> #include<memory.h> #include<stdlib.h> #include<string.h>using namespace std;//typedef int datatype; //类型重命名 using datatype int;//封装一个顺序表 class Seq…

app抓包 chrome://inspect/#devices

一、前言&#xff1a; 1.首先不支持flutter框架&#xff0c;可支持ionic、taro 2.初次需要翻墙 3.app为debug包&#xff0c;非release 二、具体步骤 1.谷歌浏览器地址&#xff1a;chrome://inspect/#devices qq浏览器地址&#xff1a;qqbrowser://inspect/#devi…

新媒体运营

一、新媒体运营的概念 1.新媒体 2.新媒体运营的五大方向 用户运营 产品运营 。。。 二、新媒体的岗位职责及要求 三、新媒体平台

快速开发与维护:探索 AndroidAnnotations

在移动应用开发的世界中&#xff0c;效率和可维护性是两个至关重要的要素。随着应用功能的不断增长和用户需求的不断变化&#xff0c;开发者们一直在寻找能够提高生产力的工具和框架。今天&#xff0c;我们将深入探讨一个能够帮助开发者实现快速开发和易于维护的框架——Androi…

dgl库安装

此篇文章继续上一篇pytorch已经安装成功的情况 &#xff08;python3.9&#xff0c;pytorch2.2.2&#xff0c;cuda11.8&#xff09; 上一篇pytorch安装教学链接 选择与之匹配的版本 输入下方代码进行测试 import dgl.data dataset dgl.data.CoraGraphDataset() print(‘Numb…

使用宝塔部署项目在win上

项目部署 注意&#xff1a; 前后端部署项目&#xff0c;需要两个域名&#xff08;二级域名&#xff0c;就是主域名结尾的域名&#xff0c;需要在主域名下添加就可以了&#xff09;&#xff0c;前端一个&#xff0c;后端一个 思路&#xff1a;访问域名就会浏览器会加载前端的代…

【Redis入门到精通二】Redis核心数据类型(String,Hash)详解

目录 Redis数据类型 1.String类型 &#xff08;1&#xff09;常见命令 &#xff08;2&#xff09;内部编码 2.Hash类型 &#xff08;1&#xff09;常见命令 &#xff08;2&#xff09;内部编码 Redis数据类型 查阅Redis官方文档可知&#xff0c;Redis提供给用户的核心数据…

【HTML5】html5开篇基础(1)

1.❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; Hello, Hello~ 亲爱的朋友们&#x1f44b;&#x1f44b;&#xff0c;这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章&#xff0c;请别吝啬你的点赞❤️❤️和收藏&#x1f4d6;&#x1f4d6;。如果你对我的…

代码随想录冲冲冲 Day51 图论Part3

101. 孤岛的总面积 dfs 首先dfs的作用就是在遇到陆地的时候找到所有的周围陆地 对于这道题的dfs 会把所有的链接边缘的陆地变成海洋 这样在全部调整之后 剩下的就是孤岛了 这道题中的dfs的结束条件就是遇到海洋时 遇到每一个陆地就会把面积1&#xff0c;在每一次重新找到…

(Java企业 / 公司项目)点赞业务系统设计-批量查询点赞状态(二)

接着上一篇文章来搞,批量查询点赞状态。这个接口提供给其他的微服务调用所以这里会用到FeignClient 直接上接口 1. 接口信息 这里是查询多个业务的点赞状态,因此请求参数自然是业务id的集合。由于是查询当前用戶的点赞状态,因此无需传递用戶信息。当前用户指的是登录用户 …

ELF文件结构

ELF文件格式的最前部是 ELF文件头&#xff08;ELF Header&#xff09; &#xff0c;包含整个文件的基本属性。然后是各个节&#xff0c;ELF文件中与节有关的结构是 “节表&#xff08;Section Header Table&#xff09;”&#xff0c;节表描述ELF文件包含的所有节的信息。 文件…

layui时间选择器选择周 日月季度年

<!-- layui框架样式 --><link type"text/css" href"/static/plugins/layui/css/layui.css" rel"stylesheet" /><!-- layui框架js --><script type"text/javascript" src"/static/plugins/layui/layui.js&qu…

MYSQL面试知识点手册

第一部分&#xff1a;MySQL 基础知识 1.1 MySQL 简介 MySQL 是世界上最流行的开源关系型数据库管理系统之一&#xff0c;它以性能卓越、稳定可靠和易用性而闻名。MySQL 主要应用在 Web 开发、大型互联网公司、企业级应用等场景&#xff0c;且广泛用于构建高并发、高可用的数据…

Qt_多元素控件

目录 1、认识多元素控件 2、QListWidget 2.1 使用QListWidget 3、QTableWidget 3.1 使用QListWidget 4、QTreeWidget 4.1 使用QTreeWidget 5、QGroupBox 5.1 使用QGroupBox 6、QTabWidget 6.1 使用QTabWidget 结语 前言&#xff1a; 在Qt中&#xff0c;控件之间…