C++模版

news2024/12/28 4:24:44

文章目录

  • C++模版
    • 1、泛型编程
    • 2、函数模版
      • 2.1、函数模版概念
      • 2.2、函数模版格式
      • 2.3、函数模版原理
      • 2.4、函数模版的实例化
      • 2.5、模板参数的匹配原则
    • 3、类模版
      • 3.1、类模版概念
      • 3.2、类模版格式
      • 3.3、类模板的实例化

img

C++模版

1、泛型编程

  • 泛型编程(Generic Programming)是一种编程范式,它强调编写可以在不同数据类型上工作的通用代码。泛型编程的目标是编写更具通用性和复用性的代码,以减少代码的重复编写,并提高代码的可维护性。

    泛型编程的主要特点包括:

    1. 通用性: 泛型编程的代码不依赖于特定的数据类型,而是能够在多种不同数据类型上工作。这使得代码更具通用性。
    2. 类型参数化: 泛型编程通过参数化类型,允许在代码中使用参数化类型的变量、函数或类。这意味着你可以编写一次通用代码,然后在不同的上下文中使用不同的类型。
    3. 类型安全: 泛型编程强调类型安全,因为它在编译时进行类型检查,避免了运行时的类型错误。
    4. 代码复用: 泛型代码可以在不同的场景中重复使用,减少了代码的冗余。

    如何实现一个通用的交换函数呢 ?

    void Swap(int &left, int &right) {
        int temp = left;
        left = right;
        right = temp;
    }
    
    void Swap(double &left, double &right) {
        double temp = left;
        left = right;
        right = temp;
    }
    
    void Swap(char &left, char &right) {
        char temp = left;
        left = right;
        right = temp;
    }
    
    //......
    int main() {
        int a = 1, b = 2;
        double c = 1.1, d = 2.2;
        Swap(a, b);
        Swap(c, d);
        return 0;
    }
    

    使用函数重载虽然可以实现,但是有以下几个不好的地方:

    1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数

    2. 代码的可维护性比较低,一个出错可能所有的重载均出错

    那能否告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码呢?

    答:C++里面有一种机制 — 模版(函数模版和类模版)

    泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。


2、函数模版

2.1、函数模版概念

  • 函数模板(Function Template)是C++中的一种机制,允许你编写可以应用于不同数据类型的通用函数。函数模板允许你编写一次通用函数定义,然后可以将不同的数据类型作为参数传递给该函数,从而自动生成特定数据类型的函数实例。

    函数模板的基本概念包括:

    1. 通用性: 函数模板允许你编写通用函数,不限于特定数据类型。这使得代码更具通用性和复用性。
    2. 类型参数: 函数模板通过使用类型参数(通常用typenameclass关键字指定)来表示可以应用于不同数据类型的函数。
    3. 实例化: 当你调用函数模板并传递特定数据类型时,编译器会根据传递的数据类型生成特定数据类型的函数实例。这个过程称为实例化
    4. 类型推导: C++编译器通常能够从传递的参数==推断==出要使用的数据类型,从而实例化函数模板。

2.2、函数模版格式

  • 格式:template<typename T1, typename T2,......,typename Tn>

  • 举例:

    • 单参数函数模版

      template<typename T>
      
      void Swap(T &a, T &b) {
          T tmp = a;
          a = b;
          b = tmp;
      }
      
      int main() {
          int a = 1, b = 2;
          double c = 1.1, d = 2.2;
          Swap(a, b);
          Swap(c, d);
          return 0;
      }
      
    • 多参数函数模版

      template<typename T1, class T2>
      
      void Swap(T1 &a, T2 &b) {
          T1 tmp = a;
          a = b;
          b = tmp;
      }
      
      int main() {
          int a = 1, b = 2;
          double c = 1.1, d = 2.2;
          Swap(a, b);
          Swap(c, d);
          Swap(a, c);
          return 0;
      }
      
    • 注意:typename是用来定义模板参数关键字,也可以使用class(切记:不能使用struct代替class)。

2.3、函数模版原理

  • 函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器。

  • 在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。

  • 注意:这三次调用的Swap不是同一个函数

    • 我们vs转到反汇编来看函数地址

2.4、函数模版的实例化

使用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化显式实例化

  • 隐式实例化让编译器根据实参推演模板参数的实际类型

    template<class T>
    
    T Add(const T &left, const T &right) {
        return left + right;
    }
    
    int main() {
        int a1 = 10, a2 = 20;
        double d1 = 10.0, d2 = 20.0;
        Add(a1, a2);//推导出a1,a2是int类型
        Add(d1, d2);//推导出d1,d2是double类型
    
        /*
        该语句不能通过编译,因为在编译期间,当编译器看到该实例化时,需要推演其实参类型
        通过实参a1将T推演为int,通过实参d1将T推演为double类型,但模板参数列表中只有一个T,
        编译器无法确定此处到底该将T确定为int 或者 double类型而报错
        注意:在模板中,编译器一般不会进行类型转换操作,因为一旦转化出问题,编译器就需要背黑锅
        Add(a1, d1);
        */
    
        // 此时有两种处理方式:1. 用户自己来强制转化 2. 使用显式实例化
        //1. 用户自己来强制转化 (隐式实例化)
        int a = 1;
        double d = 2.1;
        Add(a, (int) d);
    
        //2. 使用显式实例化
        int b = 1;
        double c = 2.1;
        Add<int>(b, c);//这里c就被强转化为int类型
        return 0;
    }
    
  • 显式实例化在函数名后的<>中指定模板参数的实际类型

    template<class T>
    
    T Add(const T &left, const T &right) {
        return left + right;
    }
    
    int main() {
      	int b = 1;
        double c = 2.1;
        Add<double>(b, c);//这里b就被强转化为double类型
        return 0;
    }
    
    • 函数参数里如果没有模版则需要显式实例化

      template<class T>
      
      T Add(const int &left, const int &right) {
          T sum = left + right;
          return sum;
      }
      
      int main() {
          
          int b = 1;
          double c = 2.1;
          int a = Add<int>(b, c);//这里b就被强转化为double类型
      
          return 0;
      }
      

    如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。

2.5、模板参数的匹配原则

  1. 一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数

    // 专门处理int的加法函数
    int Add(int left, int right) {
        return left + right;
    }
    
    // 通用加法函数
    template<class T>
    T Add(T left, T right) {
        return left + right;
    }
    
    int main() {
        Add(1, 2); // 与非模板函数匹配,编译器不需要特化
        Add<int>(1, 2); // 调用编译器特化的Add版本
        return 0;
    }
    

  2. 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板

    // 专门处理int的加法函数
    int Add(int left, int right) {
        return left + right;
    }
    
    // 通用加法函数
    template<class T1, class T2>
    T1 Add(T1 left, T2 right) {
        return left + right;
    }
    
    int main() {
        Add(1, 2); // 与非函数模板类型完全匹配,不需要函数模板实例化
        Add(1, 2.0); // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函数
        return 0;
    }
    

  3. 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换


3、类模版

3.1、类模版概念

  • 类模板(Class Template)是C++中的一种机制,允许你定义通用类,其中的数据成员和成员函数可以适用于不同的数据类型。类模板允许你编写一次通用类定义,然后可以将不同的数据类型作为模板参数传递给该类,从而自动生成特定数据类型的类实例

    类模板的基本概念包括:

    1. 通用性: 类模板允许你编写通用类,不限于特定数据类型。这使得代码更具通用性和复用性。
    2. 类型参数: 类模板通过使用类型参数(通常用typenameclass关键字指定)来表示可以应用于不同数据类型的类。
    3. 实例化: 当你创建类模板的对象时,编译器会根据传递的数据类型生成特定数据类型的类实例。这个过程称为实例化。
    4. 类型推导: C++编译器通常能够从传递的参数==推断==出要使用的数据类型,从而实例化类模板。

3.2、类模版格式

  • 格式:

    template<class T1, class T2, ..., class Tn>
    class 类模板名
    {
    	 // 类内成员定义
    };
    
  • 举例:

    // 动态顺序表
    // 注意:Vector不是具体的类,是编译器根据被实例化的类型生成具体类的模具
    template<class T>
    class Vector {
    public :
        Vector(size_t capacity = 10)
                : _pData(new T[capacity]), _size(0), _capacity(capacity) {}
    
        // 使用析构函数演示:在类中声明,在类外定义。
        ~Vector();
    
        void PushBack(const T &data);
    
        void PopBack();
        // ...
    
        size_t Size() { return _size; }
    
        T &operator[](size_t pos) {
            assert(pos < _size);
            return _pData[pos];
        }
    
    private:
        T *_pData;
        size_t _size;
        size_t _capacity;
    };
    
    // 注意:类模板中函数放在类外进行定义时,需要加模板参数列表
    template<class T>
    Vector<T>::~Vector() {
        if (_pData)
            delete[] _pData;
        _size = _capacity = 0;
    }
    
    class Date {
    public:
        Date() : _year(1), _month(1), _day(1) {
        }
    
    private:
        int _year;
        int _month;
        int _day;
    };
    
  • 注意:Vector不是具体的类,是编译器根据被实例化的类型生成具体类的模具

3.3、类模板的实例化

  • 类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类

    // Vector是类名, Vector<类型>才是类型
    int main() {
        Vector<int> it;
        Vector<Date> dt;
        return 0;
    }
    

OKOK,C++模版就到这里。如果你对Linux和C++也感兴趣的话,可以看看我的主页哦。下面是我的github主页,里面记录了我的学习代码和leetcode的一些题的题解,有兴趣的可以看看。

Xpccccc的github主页

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

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

相关文章

华清远见嵌入式学习——C++——作业4

作业要求&#xff1a; 代码&#xff1a; #include <iostream>using namespace std;class Stu {friend const Stu operator*(const Stu &L,const Stu &R);friend bool operator<(const Stu &L,const Stu &R);friend Stu operator-(Stu &L,const S…

2022年高校大数据挑战赛A题工业机械设备故障预测求解全过程论文及程序

2022年高校大数据挑战赛 A题 工业机械设备故障预测 原题再现&#xff1a; 制造业是国民经济的主体&#xff0c;近十年来&#xff0c;嫦娥探月、祝融探火、北斗组网&#xff0c;一大批重大标志性创新成果引领中国制造业不断攀上新高度。作为制造业的核心&#xff0c;机械设备在…

KEPserver和S7-200SMART PLC通信配置

KEPserver和S7-1200PLC通信配置,请查看下面文章链接: https://rxxw-control.blog.csdn.net/article/details/134683670https://rxxw-control.blog.csdn.net/article/details/134683670 1、OPC通信应用 2、选择Siemens驱动 3、添加S7-200设备

百度/抖音/小红书/微信搜索品牌形象优化怎么做?

搜索口碑是网络营销不可或缺的一部分&#xff0c;企业如何做好品牌搜索口碑优化呢&#xff1f;小马识途营销顾问建议从以下几方面入手。 1. 通过关键字优化提高自身知名度 通过对竞争对手和目标客户的关键字进行分析&#xff0c;企业可以确定哪些关键字可以提高自身品牌知名度。…

数据结构与算法-静态查找表

&#x1f31e; “清醒 自律 知进退&#xff01;” 查找 &#x1f388;1.查找的相关概念&#x1f388;2.静态查找表&#x1f52d;2.1静态查找表的类定义&#x1f52d;2.2顺序查找&#x1f52d;2.3二分查找&#x1f50e;二分查找例题 &#x1f52d;2.4分块查找&#x1f52d;2.5三…

SQL面试题,判断if的实战应用

有如下表&#xff0c;请对这张表显示那些学生的成绩为及格&#xff0c;那些为不及格 1、创建表&#xff0c;插入数据 CREATE TABLE chapter8 (id VARCHAR(255) NULL,name VARCHAR(255) NULL,class VARCHAR(255) NULL,score VARCHAR(255) NULL );INSERT INTO chapter8 (id, n…

非应届生简历模板13篇

无论您是职场新人还是转行求职者&#xff0c;一份出色的简历都是获得心仪岗位的关键。本文为大家精选了13篇专业的非应届生简历模板&#xff0c;无论您的经验如何&#xff0c;都可以灵活参考借鉴&#xff0c;提升自己的简历质量。让简历脱颖而出&#xff0c;轻松斩获心仪职位&a…

02数仓平台Zookeeper

概述 ZooKeeper是一种分布式协调服务&#xff0c;用于管理大型主机集。在分布式环境中协调和管理服务是一个复杂的过程。ZooKeeper通过其简单的架构和API解决了这个问题。ZooKeeper允许开发人员专注于核心应用程序逻辑&#xff0c;而不必担心应用程序的分布式性质。 Zookeepe…

Dart编程基础 - 一种新的编程语言

Dart编程基础 – 一种新的编程语言 Dart Programming Essentials - A New Type of Programming Language By JacksonML Dart is a client-optimized language for fast apps on any platform From dart.dev 在1999年之前&#xff0c;和我一样对计算机技术感兴趣的伙伴们&…

高级算法设计与分析练习1-10

文章目录 7-1 锦标赛7-2 选我啊&#xff01;7-3 朋友圈7-4 最短路径7-5 ICPC保定站7-6 填数字7-7 Werewolf7-8 球队“食物链”7-9 代码排版7-10 至多删三个字符 7-1 锦标赛 HBU有2 n名ACM选手&#xff0c;编号依次为1−2 n。他们现在要进行一场程序设计比赛&#xff0c;这个比…

规则引擎专题---1、什么是规则引擎

什么是规则引擎&#xff0c;为了更易大家理解&#xff0c;我们这边先抛出一个问题。 问题 现有一个在线申请信用卡的业务场景&#xff0c;用户需要录入个人信息&#xff0c;如下图所示&#xff1a; 通过上图可以看到&#xff0c;用户录入的个人信息包括姓名、性别、年龄、学…

基于51单片机的交通灯_可调时间_夜间+紧急模式

51单片机交通灯 1 讲解视频&#xff1a;2 功能要求3 仿真图&#xff1a;4 原理图PCB5 实物图6 程序设计&#xff1a;7 设计报告8 资料清单&#xff08;提供资料清单所有文件&#xff09;&#xff1a;设计资料下载链接&#xff1a; 51单片机简易交通灯_可调时间_夜间紧急 仿真代…

三、Linux高级命令

目录 1、重定向命令 1.1 重定向 > 1.2 重定向 >> 该章节的所有操作都在/export/data/shell目录进行&#xff0c;请提前创建该目录。 mkdir -p /export/data/ 1、重定向命令 1.1 重定向 > Linux 允许将命令执行结果重定向到一个文件&#xff0c;本应显示在…

「Verilog学习笔记」自动贩售机1

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 自动贩售机中可能存在的几种金额&#xff1a;0&#xff0c;0.5&#xff0c;1&#xff0c;1.5&#xff0c;2&#xff0c;2.5&#xff0c;3。然后直接将其作为状态机的几种状…

HTTP 基本概念(计算机网络)

一、HTTP 是什么&#xff1f; HTTP(HyperText Transfer Protocol) &#xff1a;超文本传输协议。 HTTP 是一个在计算机世界里专门在「两点」之间「传输」文字、图片、音频、视频等「超文本」数据的「约定和规范」。 「HTTP 是用于从互联网服务器传输超文本到本地浏览器的协议…

接口测试工具:Jmeter详解

安装 使用JMeter的前提需要安装JDK&#xff0c;需要JDK1.7以上版本 目前在用的是JMeter5.2版本&#xff0c;大家可自行下载解压使用 运行 进入解压路径如E: \apache-jmeter-5.2\bin&#xff0c;双击jmeter.bat启动运行 启动后默认为英文版本&#xff0c;可通过Options – C…

仿真的整体框架和类图设计

之前的写的模拟代码没有模块&#xff0c;没有对象&#xff0c;写的逻辑结构也很混乱。我花了些时间进行整理&#xff0c;首先所有的类如下图 在管理类中有统一的管理类的接口 &#xff0c;提供所有管理类的虚拟初始化和关闭方法 然后事件的管理类 我希望在这个类中管理所有的脉…

匿名结构体类型、结构体的自引用、结构体的内存对齐以及结构体传参

文章目录 &#x1f680;前言&#x1f680;结构体✈️结构体类型的声明✈️结构体变量的创建与初始化✈️结构体类型的特殊声明✈️结构体的自引用✈️结构体的内存对齐&#x1f681;修改默认对齐数 ✈️结构体传参 &#x1f680;前言 在C语言中有着各种数据类型&#xff0c;这…

服务注册发现 配置中心 springcloud alibaba nacos

文章目录 0100 系统环境0200 nacos安装0201 下载0202 安装 0300 工程说明0301 结构说明0302 运行效果 0400 代码说明0401 服务提供者&#xff08;Provider Service&#xff09;0402 服务消费者&#xff08;Consumer Service&#xff09;服务提供者SDK&#xff08;Provider Serv…

应用商店优化之利用季节性提高应用曝光

在应用商店中利用季节性优化&#xff0c;是提高应用和游戏的曝光度以及应用商店转化率的最有效策略之一。 1、季节性的影响。 用户消费来自许多不同渠道的新闻和信息&#xff0c;这会影响他们做出决策的方式。比如在节日期间&#xff0c;当用户寻找购物类型的应用时&#xff0…