C++泛型编程——模板,容器实现

2023-10-29

泛型编程

泛型编程是编写和类型无关的逻辑代码,是代码复用的另一种手段。模板是实现泛型编程的一种技术。

以往要编写一个通用的函数有3种方法,函数重载,使用公共基类,宏函数。

然而函数重载需要对各种类型一一枚举,且一个错个个错。第二种继承公共基类并重写虚函数实现多态,失去了类型检查,对每一个子类维护也很麻烦。宏函数也没有类型检查。

实现Vector和List容器https://github.com/zzaiyuyu/Vector-List

模板技术

模板实例化

不管是类模板或是函数模板,都不是真正的类或函数,只是一个编译器用来生成代码的蓝图

模板的实例化指函数模板(类模板)生成模板函数(模板类)的过程。对于函数模板而言,模板实例化之后,会生成一个真正的函数。而类模板经过实例化之后,只是完成了类的定义,模板类的成员函数需要到调用时才会被初始化。模板的实例化分为隐式实例化和显示实例化。

隐式实例化:在发生模板函数调用或者模板类时,才进行实例化。

//隐式实例化函数模板
template <typename T> 
T Max(const T& t1,const T& t2){
    return (t1>t2)?t1:t2;
}
//隐式实例化类模板
template <typename T>
class A{
    T num;
}

显示实例化:不管有无调用,只要显式声明,必定实例化出模板类或函数

//用template声明一下函数模板
template void func<int>(const int&);
//类模板
template class theclass<int>;

模板的使用

对函数模板的使用而言,分为两种调用方式,一种是显示模板实参调用(显示调用),一种是隐式模板实参调用(隐式调用)。对于类模板的使用而言,没有隐式模板实参和显式模板实参使用的说法,因为类模板的使用必须显示指明模板实参

  1. 隐式调用,编译器根据调用的实参推演出匹配的模板函数。
  2. 显示调用,由用户决定调用的实参类型,不经过参数推演
template <typename T> 
T Max(const T& t1,const T& t2){
    return (t1>t2)?t1:t2;
}

int main(){
    int i=5;
    cout<<Max(i,'a')<<endl; //隐式调用,没有匹配的参数无法通过编译
    cout<<Max<int>(i,'a')<<endl; //显示调用,强转int,通过编译
}

模板参数

template<typename T, size_t N>      //模板参数,其中T是类型参数,N是非类型参数
void PrintArray(const T (&array)[N]) { 
    for(size_t i = 0; i < N; ++i)     
    cout<<array[i]<<" "; 
    cout<<endl; 
}

int arr[10];
PrintArray(arr);    //调用参数

<>里typename后跟类型参数,其他为非类型参数。非类型参数N会根据实参决定,作为常量在函数模板里使用。

模板参数的作用域在紧跟的函数模板里有效。

模板特化

函数模板有全特化,类模板有全特化和偏特化。

有时候在一个泛型模板里并不能正确处理所有的类型,所以需要特化。

函数模板特化

//函数模板
template<class T>
bool IsEqual(T t1,T t2){
    return t1==t2;
}

template<> //函数模板特化
bool IsEqual(char *t1,char *t2){
    return strcmp(t1,t2)==0;
}

另外函数重载也可以实现函数模板特化的功能

bool IsEqual(char *t1,char *t2){
    return strcmp(t1,t2)==0;
}

如果使用普通重载函数,那么不管是否发生实际的函数调用,都会在目标文件中生成该函数的二进制代码。分离编译模式下,应该在各个源文件中包含重载函数的声明重载的函数。

类模板特化

全特化:模板中参数全部被固定,相当于定义一个全新的类

偏特化:模板参数没有全部固定,对部分模板参数进行指定限制

类模板全特化的应用场景——类型萃取

struct TrueType {
    static bool Get()
    {
        return true;
    }
};

struct FalseType {
    static bool Get()
    {
        return false;
    }
};
//如果没有特化,就是自定义类型
template<class T>
struct TypeTraits {
    typedef FalseType PODTYPE;
};
template <>
struct TypeTraits<int> {
    typedef TrueType PODTYPE;
};
template <>
struct TypeTraits<double> {
    typedef TrueType PODTYPE;
};
//调用
//TypeTraits<T>::PODTYPE::Get()

偏特化不仅是对部分参数的特化,同时可以是对参数的限制

常见的有将参数特化为绝对类型,指针类型

// 局部特化两个参数为指针类型
template <typename T1, typename T2> 
class Data <T1*, T2*> {
public :    
    Data(); 
private :   
    T1 _d1 ;   
    T2 _d2 ;   
    T1* _d3 ;  
    T2* _d4 ;   
}; 
template <typename T1, typename T2> 
    Data<T1 *, T2*>:: Data() { 
    cout<<"Data<T1*, T2*>" <<endl; 
}

容器适配器

已有的类模板比如vector,list,deque对操纵数据的封装,称为容器。进一步想实现一些数据结构可以借助容器的接口快速实现。

template<class T, class Container = SeqList<T> > 
class{
    ...
private:
    Container _con;
}

分离编译模式

https://blog.csdn.net/pongba/article/details/19130

上文总结一下:

每个cpp文件都会先把包含的.h复制过来,然后编译成一个单独的obj目标文件。正常情况下一个cpp里找不到其他cpp文件里的函数,会在链接期间从其他obj文件的导出符号表里找到需要的函数,并把函数地址填到自己的调用函数处。

由于模板的特殊性,只有在同一个cpp文件里发现有调用才会实例化出真正的模板函数,当函数模板单独放在一个cpp里,编译器就不会为其实例化,在链接期间别人也不可能找得到没有实例化的函数。

解决方案:

  1. 在模板头文件 xxx.h 里面显示实例化
  2. 将声明和定义放到一个文件 “xxx.hpp” 里面

hpp实质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件,则该类的调用者只需要include该hpp文件即可.**实现代码将直接编译到调用者的**obj文件中,不再生成单独的obj

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++泛型编程——模板,容器实现 的相关文章

  • 使用路由器DDNS功能+动态公网IP实现外网访问(花生壳)

    找电信开通了动态公网IP 理由是为了更流畅看家里的监控 动态公网IP一直变 所以就用DDNS tp link路由器中设置花生壳的DDNS 登录成功了 域名有一个是注册花生壳后送给你的一个免费壳域名 打开花生壳客户端 首先要删掉内网穿透的全部
  • 408知识点-计算机组成原理

    计算机组成原理 408系列参考王道2021系列书籍 文章目录 计算机组成原理 前言 绪论 数据的表示 存储系统 指令系统 中央处理器 总线 输入 输出系统 总结 前言 今天正式放假 虽然已经咸鱼了三周了 考研初试结束 把我记在我的笔记本上的
  • 华为OD机试 - 字符串分割(二)(Java)

    题目描述 给定一个非空字符串S 其被N个 分隔成N 1的子串 给定正整数K 要求除第一个子串外 其余的子串每K个字符组成新的子串 并用 分隔 对于新组成的每一个子串 如果它含有的小写字母比大写字母多 则将这个子串的所有大写字母转换为小写字母
  • PDF转换工具

    分享书籍 数据 软件等资料 分享考研经验 导师选择 读研故事 科研技巧 软件包括 PDF转换工具 Photoshop Python Matlab Spss CAD SQL R语言 Mysql等软件 公众号内 回复软件名称即可获取
  • Java【抽象类和接口】是什么?

    文章目录 前言 一 抽象类 1 什么是抽象类 2 抽象类的特征 3 抽象类的作用 二 接口 1 什么是接口 2 语法规范 3 接口的使用 4 接口的特征 5 实现多个接口 6 接口间的继承 总结 前言 各位读者好 我是小陈 这是我的个人主页
  • java发起http请求调用post和get接口

    一 java调用post接口 1 使用URLConnection或者HttpURLConnection java自带的 无需下载其他jar包 URLConnection方式调用 如果接口响应码被服务端修改则无法接收到返回报文 只能当响应码正
  • 机器学习 —— 朴素贝叶斯

    朴素贝叶斯 贝叶斯公式 P A B P A P B A P B 一个例子 现分别有 A B 两个容器 在容器 A 里分别有 7 个红球和 3 个白球 在容器 B 里有 1 个红球和 9 个白球 现已知从这两个容器里任意抽出了一个球 且是红球
  • JVM-垃圾回收

    目录 1 如何判断对象可以回收 1 1引用计数法 1 3四种引用 1 3 1强引用 1 3 2软引用 1 3 3弱引用 1 3 4虚引用 1 3 5终结器引用 2 垃圾回收算法 2 1标记清除 2 2标记整理 2 3复制 3 分代垃圾回收
  • unity游戏关卡解锁和未解锁时的不同图片以及可或不可按下

    若想让按钮不可按只要将interactable的勾勾关掉就可以了 一般用做未解锁的关卡 public void UpdateOnce 用于更新过关数 没解锁的抑制 for int i 0 i
  • 分享web前端七款HTML5 Loading动画特效集锦

    以前我们大部分的Loading动画都是利用gif图片实现的 这种图片实现Loading动画的方法虽然也很不错 但是作为HTML5开发者来说 如果能利用HTML5和CSS3实现这些超酷的Loading动画 那将是一件非常痛快的事情 1 HTM
  • 生产环境elasticsearch的配置建议

    以下主要来自官方文档 主要分为几块 硬件方面 内存 CPU 硬盘 网络 其他 操作系统 较大的文件描述符 设置MMap 管理工具 JVM虚拟机 请不要调整JVM设置 请不要修改垃圾收集器 给lucene留下一半的内存空间 不要超过32G 避
  • CentOS7安装Oracle数据库的全流程

    一 准备工作 1 下载Oracle的安装介质 Oracle 11g R2 Linux版本有两个压缩文件包 都需下载安装才会完整 linux x64 11gR2 database 1of2 zip linux x64 11gR2 databa
  • ip 和 iphdr

    1 struct ip 和struct iphdr struct ip if BYTE ORDER LITTLE ENDIAN u char ip hl 4 header length ip v 4 version endif if BYT
  • 数组也是对象

    一个对象中的属性名不仅仅是字符串格式 还有可能是数字格式的 当我们存储的属性名不是字符串也不是数字的时候 浏览器会把这个值转换为字符串 toString 然后在进行存储 obj 300 gt 先把 toString 后的结果作为对象的属性名
  • 处理递归数据的键名

    tortoise data 使用递归函数 if data data length lt 0 递归的出口 return null return data map e gt 循环数据 const model name e label id e
  • 剑指offer 学习笔记 圆圈中最后剩下的数字

    面试题62 圆圈中最后剩下的数字 0 1 n 1这n个数字排成一个圆圈 从数字0开始 每次从这个圆圈里删除第m个数字 求出这个圆圈里剩下的最后一个数字 本题就是约瑟夫环问题 法一 用环形链表模拟圆圈 我们可以直接用标准库的list模拟环形链
  • [转]怎样在systemverilog DPI中调用SV,C与C++(二)

    有的时候需要交互struct union数据类型 下面举个简单例子 在SV里定义这个一个结构体 typedef struct int id string name xaction 同样的 在C里定义同样的结构体 结构体名可以不一致 type
  • Android 数据库框架GreenDao

    参考详情网站 Android 数据库框架 GreenDao org greenrobot greendao 起航 当风起时的博客 CSDN博客
  • java的string常用方法_java中String类的常用方法

    public class HelloWorld public static void main String args Java文件名 String fileName HelloWorld java 邮箱 String email laur

随机推荐

  • Pandas分组、聚合、过滤操作全面解析!

    gt gt gt import numpy as np gt gt gt import pandas as pd gt gt gt df pd read csv data table csv index col ID gt gt gt df
  • Redisson-分布式锁-闭锁

    Redisson 分布式锁 闭锁 引入必要依赖
  • 以色列技术!Amimon无线WHDI技术解析

    转自 http www pcpop com doc 0 579 579310 all shtml Amimon WHDI技术独家解析 泡泡网高清频道9月23日 今年年初 本站独家撰写有关无线技术的展望性文章 Intel Android 天幕
  • 慢~再听我讲一遍Activity的启动流程

    前言 activity启动的流程分为两部分 一是在activity中通过startActivity Intent intent 方法启动一个Activity 二是我们在桌面通过点击应用图标启动一个App然后显示Activity 第二种方式相
  • 5个可以激发设计灵感的AI工具推荐

    当设计灵感耗尽 陷入创作瓶颈时 人工智能艺术生成器可能会为您提供新的启示 这些基于深度学习和发展 神经网络 的工具可以将输入的文本描述或图像转换成各种风格的艺术作品 并提供丰富的风格参数和材料库 让您可以自由调整和创作 无论是专业设计师还是
  • R语言中读取和处理文件的常用方法

    测试文件放在rawdata 目录下 包含以下内容 我在rawdata下存放了以上文件 目录 1 dir 2 list files 3 dir ls 4 整理文件下的内容 重要 获得包含特定字符串的文件 获得文件绝对路径 将文件粘贴至另一个文
  • JAVA根据模板生成WORD文件并导出

    JAVA根据模板生成WORD并导出 实现功能 一 WORD导出效果 二 编写WORD模板 三 引入所需maven依赖 四 JAVA代码工具类 五 配置信息说明 六 在固定位置插入表格 6 1 情况说明 6 2 编码实现 6 3 导出效果 七
  • javaWeb学习笔记 --- Html

    HTML html是超文本标记语言 它规定了自己的语法规则 用来表示比 文本 更丰富的意义 比如图片 表格 链接等 目前互联网上的绝大部分网页都是使用HTML编写的 html的结构
  • 前端ssh自动部署

    1 先安装两依赖包 archiver 是用来压缩dist文件 node ssh用来和ssh链接登录以及命令的执行 npm install node ssh archiver save 2 在根目录建一个文件 我这里给它取名upload js
  • linux查找目录

    要在Linux中查找目录 可以使用find命令 下面是查询目录的几个示例 1 查找当前目录下所有子目录 find type d 2 在指定路径下查找目录 find path to directory type d 3 查找以特定名称开头的目
  • restful风格API

    一 什么是API API Application Programming Interface 应用程序编程接口 是一些预先定义的函数 目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力 而又无需访问源码 或理解内部工作机制的
  • D0002-数据类型转换与运算符

    数据类型转换 1 隐式 自动 类型转换 从数据类型小的到数据类型大的转换 都是数字型的 布尔类型不参与 byte lt short lt int lt long lt float lt double char lt int lt long
  • Netty概述

    1 Netty 概述 1 1 Netty 简介 Netty 官网上可以看到最权威的介绍 Netty 是一个异步事件驱动的网络应用程序框架 用于快速开发可维护的高性能服务器和客户端 Netty 是一个 NIO 客户机 服务器框架 它支持快速
  • 判断正整数的正则表达式

    正数的正则表达式 包括0 小数保留两位 0 1 d 1 2 1 9 d 1 d 1 2 1 9 d 0 正数的正则表达式 不包括0 小数保留两位 0 1 d 1 2 1 9 d 1 d 1 2 1 9 d 正整数的正则表达式 包括0 0 1
  • OSI和TCP/IP

    1 OSI和TCP IP 1 1 模型对比 OSI七层 TCP IP五层 TCP IP四层 应用层 应用层 应用层 表示层 会话层 传输层 传输层 传输层 网络层 网络层 网络层 数据链路层 数据链路层 网络接口层 物理层 物理层 1 2
  • i5十代不能装win7系统_戴尔台式机i5十代CPU,3991或3881,Win10改win7方法

    戴尔台式机3991或3881 Win10改win7方法如下为精简步聚 希望能给大家有所帮助 电脑的配置为i5 10500十代CPU DDR4代内存 一 WinPE要求 小兵PE2020版 里面有注入USB3 X及NVME驱动和小兵系统安装软
  • C语言中有符号和无符号的区别(signed与unsigned)

    include
  • Maven构建与管理项目(三)

    Maven构建与管理项目 三 Maven与Eclipse整合 安装Maven插件 下载下来的maven插件如下图所示 插件存放的路径是 E MavenProject Maven2EclipsePlugin 进入到eclipse中的dropi
  • 使用langchain+chatGPT搭建自有知识库问答机器人

    前言 自去年年底OpenAI发布ChatGPT以来 大型语言模型在人工智能领域掀起了一股热潮 随后 各家公司纷纷推出自己的大型语言模型 如百度的文心一言 讯飞的星火大模型等 在这个过程中 文本转图片和文本转视频等相关领域也备受关注 然而 很
  • C++泛型编程——模板,容器实现

    泛型编程 模板技术 模板实例化 模板的使用 模板参数 模板特化 函数模板特化 类模板特化 容器适配器 分离编译模式 泛型编程 泛型编程是编写和类型无关的逻辑代码 是代码复用的另一种手段 模板是实现泛型编程的一种技术 以往要编写一个通用的函数