C++快速理解之泛型编程

news2024/11/25 1:01:46

1、引入

#include <iostream>

using namespace std;

int add(int a, int b) {
    return a + b;
}

float add(float x, float y) {
    return x + y;
}

int main() {

    int result = add(3, 4);
    cout << "result  = " << result << endl;

    float result2 = add(3.5f, 4.5f);
    cout << "result2 = " << result2 << endl;

    return 0;
}

在这里插入图片描述
上述的例子,虽然能够实现计算2个数值的求和计算,但是明显感觉到,代码重复太多了
有没有一种情况使得编码的时候暂时的忽略掉类型这个特性,等运行时在动态决定的呢?

有,泛型

2、泛型编程

是什么?
泛型编程是一种编程范式
它允许在编写代码时使用泛化的数据类型和算法,以增加代码的可重用性和灵活性

怎样做?
在 C++ 中,泛型编程主要通过模板(Templates)来实现
泛型编程的核心思想是编写与特定数据类型无关的代码使代码能够适用于多种数据类型而不需要重复编写
通过使用泛型,可以编写通用的数据结构和算法,使其适用于不同的数据类型,从而提高代码的复用性和扩展性

模板是什么?
模板是一种将类型参数化的工具,可以用来定义通用的类、函数和算法
通过使用模板,可以编写可以适用于多种数据类型的代码

C++ 提供了类模板(Class Templates)和函数模板(Function Templates)来支持泛型编程

template <typename T>
T 函数名(){}

简单的示例,演示了在 C++ 中使用函数模板实现泛型编程:

#include <iostream>

// 函数模板
template <typename T>
T maximum(T a, T b) {
  return (a > b) ? a : b;
}

int main() {
  int intMax = maximum(10, 20); // 调用 maximum 函数,类型推导为 int
  std::cout << "Maximum of 10 and 20 is: " << intMax << std::endl;

  double doubleMax = maximum(3.14, 2.71); // 调用 maximum 函数,类型推导为 double
  std::cout << "Maximum of 3.14 and 2.71 is: " << doubleMax << std::endl;

  return 0;
}

在上述示例中,定义了一个函数模板 maximum,它接受两个类型相同的参数,并返回较大的值。通过使用 typename 和模板参数 T,我们将类型参数化,使函数能够适用于不同的数据类型。
在 main 函数中,我们调用了 maximum 函数两次,一次传递整数参数,一次传递双精度浮点数参数。编译器根据传递的参数类型自动推导出模板参数 T 的具体类型,并生成适当的函数代码。

通过泛型编程,我们可以编写通用的函数模板,能够适应多种数据类型的需求,从而提高代码的复用性和灵活性。泛型编程是 C++ 中强大的特性之一,它使得编写通用、可扩展的代码变得更加容易。

3、函数模板

在 C++ 中,一个函数模板可以对应多个函数。当使用模板生成代码时,编译器会根据传递的参数类型实例化对应的函数

函数模板本身并不是一个具体的函数定义,而是一个通用的模板,用于生成特定类型的函数定义。当编译器在代码中遇到对函数模板的调用时,它会根据传递的参数类型生成具体的函数定义

#include <iostream>

template <typename T>
void printValue(T value) {
    std::cout << "Value: " << value << std::endl;
}

int main() {
    printValue(10);      // 调用 printValue<int>(int)
    printValue(3.14);    // 调用 printValue<double>(double)

    return 0;
}

4、函数模板重载

如普通函数一般,函数模板也可以重载,以便灵活应对更多的需求

#include <iostream>

using namespace std;

template<typename T>
T add(T t1, T t2) {
    T ret;
    ret = t1 + t2;
    return ret;
}

template<typename T>
T add(T t1, T t2, T t3) {
    T ret;
    ret = t1 + t2 + t3;
    return ret;
}

int main() {

    int result1 = add(1, 2);
    int result2 = add(1, 2, 3);

    cout << "result1 = " << result1 << endl;
    cout << "result2 = " << result2 << endl;

    return 0;
}

5、多个参数的函数模板

当需要使用多个参数的函数模板时,可以在模板定义中添加额外的类型参数。这样,实例化函数模板时可以提供多个类型参数,并根据需要进行实例化。

下面是一个示例,演示了一个具有两个类型参数的函数模板的定义和使用:

#include <iostream>

template <typename T, typename U>
void PrintPair(T first, U second) {
    std::cout << "Pair: " << first << ", " << second << std::endl;
}

int main() {
    PrintPair(10, 3.14);                    
    // 实例化函数模板为 PrintPair<int, double>(10, 3.14)
    PrintPair("Hello", std::string("World"));   
    // 实例化函数模板为 PrintPair<const char*, std::string>
    //("Hello", std::string("World"))

    return 0;
}

在上述示例中,我们定义了一个名为 PrintPair 的函数模板,它接受两个类型参数 T 和 U。该函数模板用于打印两个值,分别表示键和值。

在函数模板中,我们使用 T first 和 U second 分别定义了两个函数参数。我们可以像普通函数一样使用这些参数,并在函数体中执行相应的操作。

在 main 函数中,我们使用 PrintPair 函数模板进行调用,并传递不同类型的参数。编译器会根据实际的参数类型实例化函数模板,并生成具体的函数定义。

当然,也可以重载

通过这个案例,我们可以看到如何定义并使用具有多个参数的函数模板。可以根据实际需要提供不同的类型参数,从而创建具有不同类型参数的通用函数。这提供了更大的灵活性和代码重用性。

6、类模板
类模板(Class Template)是 C++ 中用于创建通用类的特性。它允许定义一个模板,其中的类型参数可以在使用时被实例化为具体的类型,从而创建多个具有相似结构和行为的类。

类模板的定义形式如下:

template <typename T>
class ClassName {
    // 类成员和成员函数定义
};

template 表示这是一个类模板,并使用 T 作为类型参数。T 可以是任意合法的标识符,用于表示通用的类型

#include <iostream>

template<typename T>
class DynamicArray {
private:
    T *elements;  // 动态数组的指针
    int size;     // 数组的大小

public:
    DynamicArray(int s) : size(s) {
        elements = new T[size];  // 根据指定大小分配内存
    }

    ~DynamicArray() {
        delete[] elements;  // 释放内存
    }

    void Add(T element) {
        // 添加元素到数组
        // 省略具体的实现逻辑
    }

    T Get(int index) {
        // 获取指定索引处的元素
        // 省略具体的实现逻辑
    }

    int Size() {
        return size;  // 返回数组的大小
    }
};

int main() {
    class DynamicArray<int> intArray(5);           // 创建一个存储整数的动态数组
    class DynamicArray<double> doubleArray(10);    // 创建一个存储双精度浮点数的动态数组

    intArray.Add(10);                        // 向整数数组中添加元素
    doubleArray.Add(3.14);                    // 向双精度浮点数数组中添加元素

    int value = intArray.Get(0);              // 从整数数组中获取元素
    double doubleValue = doubleArray.Get(0);  // 从双精度浮点数数组中获取元素

    std::cout << "Integer array size: " << intArray.Size() << std::endl;
    std::cout << "Double array size: " << doubleArray.Size() << std::endl;

    return 0;
}

在这里插入图片描述
在上述示例中,我们定义了一个名为 DynamicArray 的类模板。它具有一个类型参数 T,用于表示动态数组中的元素类型。

在类模板中,我们使用 T* elements 定义了一个动态数组的指针,并使用 int size 定义了数组的大小。构造函数负责根据指定的大小分配内存,析构函数负责释放内存。

我们还提供了 Add 函数用于向数组中添加元素,Get 函数用于获取指定索引处的元素,Size 函数用于返回数组的大小。

在 main 函数中,我们使用不同的类型实例化了 DynamicArray 类模板,并演示了添加元素、获取元素以及获取数组大小的操作。

通过这个案例,我们可以看到类模板的通用性和灵活性。它使我们能够使用相同的代码定义不同类型的动态数组,从而提供了代码重用和泛型编程的好处。

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

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

相关文章

智能分班结果自动发布系统

新学期&#xff0c;校园里又将迎来一批充满活力的新生。对于老师们来说&#xff0c;除了准备教学计划和课程内容&#xff0c;还有一项看似简单却颇为繁琐的任务——发布分班。传统的分班信息发布方式&#xff0c;通常是老师们一个个私信给学生家长&#xff0c;家长们收到信息后…

【图像特效系列】图像滤镜特效的实践 | 包含代码和效果图

目录 一 滤镜特效 1 代码 2 效果图 图像特效系列主要是对输入的图像进行处理,生成指定特效效果的图片。图像素描特效会将图像的边界都凸显出来;图像怀旧特效是指图像经历岁月的昏暗效果;图像光照特效是指图像存在一个类似于灯光的光晕特效,图像像素值围绕光照中心点呈圆…

InternLM2_PracticalCamp_L1_rask4_llamaindex+Internlm2 RAG实践

1. 前置知识 正式介绍检索增强生成&#xff08;Retrieval Augmented Generation&#xff0c;RAG&#xff09;技术以前&#xff0c;大家不妨想想为什么会出现这样一个技术。 给模型注入新知识的方式&#xff0c;可以简单分为两种方式&#xff0c;一种是内部的&#xff0c;即更新…

DNS查询过程与原理

目录 DNS1. DNS 是什么2. DNS 服务器3. 使用dig显示查询过程4. 域名的逐级查询5. 简述DNS解析www.baidu.com的过程 参考 DNS 1. DNS 是什么 DNS &#xff08;Domain Name System 的缩写&#xff09;是域名解析器&#xff0c;根据域名查出IP地址 2. DNS 服务器 DNS 服务器是一…

Leon黎明广州演唱会2024重磅官宣,10月26日倾情开唱!

径自奔流的时光中&#xff0c;总有些声音拥有超越时间的力量&#xff0c;弥合着世代更迭的图景&#xff0c;在一代又一代人的心中闪烁不息。在熠熠生辉的星河中&#xff0c;垂钓破晓时分的曙光&#xff0c;总有星辰会指引着我们相遇。 当千禧年的风吹过耳畔&#xff0c;记忆深…

在 ToolStrip 控件中使用工具提示

可以通过将控件的 ShowItemToolTips 属性设置为 true 来为所需的 ToolStrip 控件显示 ToolTip。 显示工具提示 将控件的 ShowItemToolTips 属性设置为 true。 ToolStrip.ShowItemToolTips 的默认值为 true&#xff0c;MenuStrip.ShowItemToolTips 和 StatusStrip.ShowItemTool…

基于HTML语言的环保网站的设计与实现

TOC springboot318基于HTML语言的环保网站的设计与实现 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&a…

如何选择有意义的B2B SEO关键词?

今天谈谈如何选择有意义的B2B SEO关键字目标&#xff0c;以及你可以在自己的关键字研究中采取的流程和步骤。B2B和我们通常看到的B2C营销类型有点不同。销售周期或实际做出购买决定所需的时间通常要长得多&#xff0c;这需要多个利益相关者的参与。个人将参与这个过程&#xff…

Redis远程字典服务器(4)—— string类型详解

目录 一&#xff0c;string基本情况 二&#xff0c;string命令详解 2.1 set命令选项 2.2 setnx&#xff0c;setex 2.3 incr&#xff0c;incrby 2.4 decr&#xff0c;decrby 2.5 append拼接 2.6 getrange获取 2.7 setrange修改 2.8 strlen获取长度 2.9 总结 三&…

迈威通信Wi-Fi无线交换机:让工业网络打破线缆束缚

随着《中国制造2025》等国家政策的推进&#xff0c;我国正在加速推动制造业向智能化和信息化转型升级。在这一背景下&#xff0c;工业互联网作为支撑智能制造的关键基础设施&#xff0c;其重要性愈发凸显。特别是在“万物互联”的今天&#xff0c;Wi-Fi不仅成为了日常生活的重要…

VIM 包,集成多种算法的数据缺失值处理工具!

生信碱移 VIM 缺失值处理 在组学分析中&#xff0c;尤其是在公开数据库的挖掘中&#xff0c;数据缺失是一个常见问题&#xff0c;这可能是由于样本处理、测量误差或技术限制等多种原因引起。例如&#xff0c;在转录组学研究中&#xff0c;某些基因的表达数据可能因实验失败而…

我主编的电子技术实验手册(15)——测量正弦信号

本专栏是笔者主编教材&#xff08;图0所示&#xff09;的电子版&#xff0c;依托简易的元器件和仪表安排了30多个实验&#xff0c;主要面向经费不太充足的中高职院校。每个实验都安排了必不可少的【预习知识】&#xff0c;精心设计的【实验步骤】&#xff0c;全面丰富的【思考习…

Qt (5)【Qt 的 qrc 机制高效管理项目静态资源】

阅读导航 引言一、qrc机制简介二、创建qrc机制并使用1. 创建⼀个qrc文件2. 添加已有资源3. 使用已加载资源 三、qrc机制的优缺点 引言 在上一篇文章中&#xff0c;我们深入探讨了QWidget作为Qt GUI框架中核心基类的重要性&#xff0c;以及它如何承载了构建丰富用户界面所需的各…

“传统”父母用手机 VS “时髦”父母玩手机

“传统”父母日常用智能手机&#xff0c;经常有些“拦路虎”&#xff0c;让他们在接触新事物的时候&#xff0c;如果搞不定就干脆不用了。现在也涌现出来很多“时髦”父母&#xff0c;能游刃有余的使用智能手机&#xff0c;如何让长辈在使用手机时更有松弛感&#xff0c;今天带…

Mapreduce_partition分区入门

分区 将输入的csv按照员工号拆分成每个员工&#xff0c;每个员工存储为员工对象&#xff0c;之后按每个员工的不同部门存储 pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:x…

力扣热题100_回溯_17_电话号码的字母组合

文章目录 题目链接解题思路解题代码 题目链接 17. 电话号码的字母组合 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 示…

力扣面试经典算法150题:删除有序数组中的重复项 II

删除有序数组中的重复项 II 今天的题目是力扣面试经典150题中的数组的中等难度题: 删除有序数组中的重复项 II 题目链接&#xff1a;https://leetcode.cn/problems/remove-duplicates-from-sorted-array-ii/description/?envTypestudy-plan-v2&envIdtop-interview-150 …

Linux中yum、vim、gcc/g++的使用

目录 一、Linux 软件包管理器 yum 什么是软件包 关于 rzsz 查看软件包★ 如何安装软件★ 如何卸载软件★ Linux 开发工具 二、Linux编译器-vim使用 vim的基本概念 vim的基本操作 vim正常模式命令集 vim末行模式命令集 vim操作总结 如果在vim界面不小心按了Ctrl …

【Redis集群】集群原理最全解析

主从集群 单节点Redis的并发能力是有上限的&#xff0c;要进一步提高Redis的并发能力&#xff0c;就需要搭建主从集群&#xff0c;实现读写分离。 数据同步概念 Replication Id和offset 在从节点发起数据同步的请求中&#xff0c;有两个重要的属性&#xff1a; Replication…

灵办AI探索之旅:颠覆传统的代码开发工具

前言 灵办AI是一个先进的人工智能工具&#xff0c;专注于提高软件开发和项目管理的效率。其核心功能包括代码生成、优化、评估和自动化修复&#xff0c;旨在帮助开发者和团队提升开发速度和代码质量。 体验地址&#xff1a;https://ilingban.com/browser_extension/?fromjj …