c++模板与泛型编程

模板的作用:通过使用模板降低重复代码的编写,把已经写好的代码作用最大化;

模板的概念

1.模板与泛型编程(目的时只进行逻辑操作,不需要考虑数据类型,将类型作为参数传递)

模板是实现代码重用的一种工具或方法,用于完成某种功能或解决某种问题,模板的作用就是实现类型参数化。

模板就是泛型编程的前置条件,属于充分但不必要条件;

总而言之:泛型编程就是为了编写和数据类型没有关系的逻辑代码,而模板就是为了实现代码逻辑和数据类型没有关系抽象的数据类,是泛型编程的先决条件;

2.模板分类

函数模板:

函数模板用于定义模板函数,模板函数就是用模板生成的函数;

类模板

类模板用于定义模板类,模板类就是用类模板定义出来的类;

总而言之:模板作用于函数就是函数模板,模板作用于类就是类模板;

函数模板和普通函数对比:

1.只要满足重载条件都可以构成重载,模板函数和普通函数之间只要满足重载条件都可以构成重载;

2.同时出现模板函数和普通函数重载,相同情况下编译器默认优先调用普通函数;

3.如果需要强制调用模板函数,可以使用显式调用的方式去调用指定的模板函数;

4.模板的局限性

// 通过函数模板定义模板函数
// 语法:
// 定义:
// template用于定义模板的关键字,typename(class)用于定义类型的关键字,Type_n为自定义的类型名称
// template <typename Tpe_1, ... , typename Type_n>
// 返回值类型 函数名(形参列表)
// {
//      函数体;
// }
// 调用:
// 函数名<指定类型>(参数列表)#include <iostream>
#include <string>using namespace std;template <typename T1, typename T2>
T1 add(T1 a, T2 b)
{return a + b;
}// class也可以用于定义类型,但是一般都用typename代替class就行
template <class TT1, class TT2>
void test1(TT1 tt1, TT2 tt2)
{cout << "tt1 = " << tt1 << ", tt2 = " << tt2 << endl;
}// class也可以用于定义类型,但是一般都用typename代替class就行
template <typename TY1, typename TY2>
void test2(TY1 tt1, TY2 tt2)
{cout << "tt1 = " << tt1 << ", tt2 = " << tt2 << endl;
}int main()
{// test1// 隐式推导类型,由编译器指定cout << "test1 : " << endl;test1(1, 2);test1(1.123, 2.123);test1("name", 'A');// test2cout << "test2 : " << endl;test2(1, 2);test2(1.123, 2.123);test2("name", 'A');// add测试cout << "add(3, 4) = " << add(3, 4) << endl;cout << "add(1.23, 1.24) = " << add(1.23, 1.24) << endl;// add(6, 2.46) = 8 输出的数据类型由编译器决定,这里返回值设置为int类型cout << "add(6, 2.46) = " << add(6, 2.46) << endl;cout << "add<int>(6, 2.46) = " << add<int>(6, 2.46) << endl;cout << "add<double>(6, 2.46) = " << add<double>(6, 2.46) << endl;// 模板函数调用,显式指定类型,告诉编译器按照指定类型操作// const char *就是string类型test1<const char *, char>("name", 'A');return 0;
}
// 模板的局限性
#include <iostream>
#include <string>using namespace std;template <typename T>
bool IsDataEqual(T a, T b)
{if (a == b) {return true;}return false;
}class MyData
{
public:int m_num;int m_val;// 添加默认构造函数,如果有自定义构造函数后系统将不会再分配默认的构造函数// 如果没有没有这个无参构造函数,那么通过MyData obj1, obj2;方式定义对象时会报错如下:// error: no matching function for call to ‘MyData::MyData()’MyData obj1, obj2;MyData() : m_num(0) {}// 自定义带参构造函数MyData(int n) : m_num(n) {}
};class MyClass
{
public:int m_num;int m_val;// 如果加上设置默认缺省参数值,可以使用MyClass obj创建对象,此时这个对象拥有设置的默认缺省参数值MyClass(double n = 5.0, double val = 6.0) : m_num(n), m_val(val) {}
};// 对自定义数据类型的对象需要自定义规则进行比较
template<typename TT> bool MyCompare(const TT &a, const TT &b)
{if (a.m_num == b.m_num) {return true;}return false;
} int main()
{int num = 5, val = 5;cout << boolalpha << IsDataEqual(num, val) << endl;val = 6;cout << (IsDataEqual(num, val) ? "true" : "false") << endl;cout << (IsDataEqual<int>(num, val) ? "true" : "false") << endl;// 自定义数据类型比较MyData obj1(5), obj2(5);// 如果没有重载==运算符,不同对象之间不可以使用模板函数进行比较cout << (MyCompare(obj1, obj2) ? "true" : "false") << endl;cout << (MyCompare<MyData>(obj1, obj2) ? "true" : "false") << endl;MyClass obj;cout << "obj.m_num = " << obj.m_num << ", obj.m_val = " << obj.m_val << endl;return 0;
}
// 模板类
// 语法:
// template<类型参数列表>
// class 模板类类名
// {
//     成员;
// }; // 定义域需要加";"// 类型参数列表:<class T1, ..., class Tn>
// 成员:T1 name; ... Tn#include <iostream>
#include <string>using namespace std;// 数据参数可用默认值,数据类型也可以使用默认值
// 默认类型可以有,也可以不写
// template <class Type1 = int, class Type2 = double>
template <class Type1, class Type2>
class MyData
{
private:Type1 m_num;Type2 m_val;
public:MyData(Type1 n = 0, Type2 v = 0.0) : m_num(n), m_val(v) {}// get/set 内联Type1 GetNum() {return m_num;}Type2 GetVal() {return m_val;}void SetNum(Type1 n) {m_num = n;}void SetVal(Type2 v) {m_val = v;}void showData();
};// 模板类需要给定类型才能完整,没给类型就不是完整类
template <typename T1, typename T2>
void MyData<T1, T2>::showData()
{cout << "num = " << m_num << ", val = " << m_val << endl;
}// 1.普通全局函数
// 普通全局函数,指定MyData类型的对象并指定模板类对象的参数
// 这种写法只能接收类型匹配的参数对象
void testFunc_1(MyData<int, double> &obj)
{cout << "testFunc_1(MyData<int, double> &obj) : " ;obj.showData();
}// 2.函数参数模板化
template <typename TT1, typename TT2>
void testFunc_2(MyData<TT1, TT2> & obj)
{cout << "testFunc_2(MyData<TT1, TT2> & obj)  : " ;obj.showData();
}// 3.整个类作为一个类型,整体参数作为一个模板传输
template <class T>
void testFunc_3(T & obj)
{cout << "testFunc_3(T & obj)  : " ;obj.showData();
}int main()
{// 如果没有设置默认参数类型则需要指定参数类型// template <class Type1, class Type2> // 未指定默认参数类型MyData<int, double> data_1(3, 3.14);testFunc_1(data_1);// 如果有设置默认参数类型,<>中可以不指定数据类型// template <class Type1 = int, class Type2 = double> // 指定默认参数类型// MyData<> data_1(3, 3.14);data_1.showData();// 模板类可以在创建对象的时候指定对象中的类型MyData<char, double> data_2(67, 3.14);data_2.showData();// 隐式调用,不指定参数类型testFunc_2(data_2);// 显示调用,指定参数类型testFunc_2<int, double>(data_1);MyData<char, float> data_3(68, 3.14);data_3.showData();// 通过以上测试可以看出同一种类型的对象数据类型不一样,这就是模板类的功能testFunc_3(data_1);testFunc_3<MyData<int, double>>(data_1);testFunc_3(data_2);testFunc_3<MyData<char, double>>(data_2);testFunc_3(data_3);testFunc_3<MyData<char, float>>(data_3);return 0;
}

// 类模板的继承
// 注意事项:
// 写模板时需要将类的声明和实现都写在同一个文件中
#include <iostream>
#include <string>using namespace std;template <class FType>
class Father
{
public:FType m_f_val;
};// 子类继承父类时需要指定参数类型
class Son : public Father<int>
{
public:int m_s_val;
};// 子类本省也可以是一个模板
template <class SType1, class SType2>
class Son1 : public Father<SType1>
{
public:int m_s_val;
};int main()
{Son1<int, double> obj_son;obj_son.m_f_val;obj_son.m_s_val;return 0;
}
// 模板与友元之间的关系
// 相当于就是在类模板中使用友元函数
#include <iostream>
#include <string>using namespace std;// 模板类友元函数能不用就不用,
// 如果非得要用,在类中声明时需要在函数名后边加上一个<>,实现函数体定义的时候不能在函数名后边加<>
// 需要在模板类友元函数前面先声明类
// 还需要在模板类友元函数前面声明函数
// 以下4行声明代码其实只需要先声明void show_2(A<T> & obj);函数即可
// 但是void show_2(A<T> & obj);函数声明的时候需要声明类型T,即template <typename T>
// template <typename T>声明类型T的时候发现类A也需要提前声明
// class A;声明类A的时候也得提前声明模板类型,即template <class T>
// 所以就有了以下4行声明
template <class T>
class A;
template <typename T>
void show_2(A<T> & obj);// 只设置一个类型,并设置默认参数类型为int,当然也可以不设置默认类型
template <class T = int>
class A
{
public:A(T t = 0) : m_a(t) {}private:T m_a;// C++ 中友元函数 `friend` 的权限与其在类中声明的访问权限是无关的,// 即无论它是在 `public`、`protected` 或 `private` 声明的,它的访问权限都是类外的,可以访问类的私有成员。// 当在类中声明一个函数为 `friend`,其实质上是将这个函数的访问权限放宽到了类的外部,使它可以访问类的私有成员。// 因此,友元函数的访问权限不受类的访问控制修饰符所限制。// 需要注意的是,友元关系是单向的,即如果类 A 作为类 B 的友元,不一定意味着类 B 作为类 A 的友元。// 另外,友元关系是不能被继承的,即派生类无法访问基类中的友元函数。friend void show_1(A<T> & obj) {cout << "show_1() : " << obj.m_a << endl;}// 其实友元函数一般只在类中声明,类外定义// show_2中的T与上文中的T没有任何联系,巧合,都称之为T// 只有在声明的时候需要在函数名后边写<>,在实现定义的时候不需要加<>friend void show_2<>(A<T>& obj);};template <typename T>
// 只有在声明的时候需要在函数名后边写<>,在实现定义的时候不需要加<>
void show_2(A<T> & obj)
{cout << "show_2() : " << obj.m_a << endl;
}int main()
{A<int> obj_a(666);show_1(obj_a);show_2(obj_a);return 0;
}

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

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

相关文章

【软件设计师】程序语言

1.程序设计语言基本概念 1.1 低级语言与高级语言 低级语言&#xff1a;机器语言和汇编语言称为低级语言 机器语言指0.&#xff0c;1组成的机器指令序列 汇编语言指用符号表示指令的语言&#xff0c;如MOV AX&#xff0c;2 高级语言&#xff1a;从人类的逻辑角度出发&#xff0…

numpy-mkl的下载地址

不要使用pip3直接在终端安装&#xff0c;因为pip3默安装的是numpy&#xff0c;而不是numpymkl。 采用在第三方库中手动下载后&#xff0c;再安装的方式。 第三方库网址&#xff1a;https://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy 如果不能进入就可以选择去git里面&#x…

(三)MobaXterm、VSCode、Pycharm ssh连接服务器并使用

背景&#xff1a;根据前两篇文章操作完成后&#xff0c; 手把手教学&#xff0c;一站式安装ubuntu及配置服务器-CSDN博客 手把手教学&#xff0c;一站式教你实现服务器&#xff08;Ubuntu&#xff09;Anaconda多用户共享-CSDN博客 课题组成员每人都有自己的帐号了&#xff0…

嵌入式0基础开始学习 Ⅲ Linux基础(3)正则表达式

0.问题引入 字符串是计算机应用中最为广泛的处理对象之一(浏览器&#xff0c;xml文件&#xff0c;代码) 并且字符串的组合规则形式各种各样&#xff0c;如&#xff1a; 数字字符串 email字符串 IP地址字符串 网址 …

互联网政务应用安全管理规定:使用安全连接方式访问

前几日&#xff0c;由中央网络安全和信息化委员会办公室、中央机构编制委员会办公室、工业和信息化部、公安部等4部门联合制定的《互联网政务应用安全管理规定》&#xff08;以下简称规定&#xff09;发布了&#xff0c;规定定义了互联网政务应用&#xff0c;也对互联网政务应用…

Android数据缓存框架 - 内存数据载体从LiveData到StateFlow

引言&#xff1a;所有成功者的背后&#xff0c;都有一份艰苦的历程&#xff0c;不要只看到了人前的风光&#xff0c;而低估了他们背后所付出的努力。 随着flow到流行度越来越高&#xff0c;有开发者呼吁我使用flow&#xff0c;于是我就如你们所愿&#xff0c;新增了StateFlow作…

智能时代下,人机交互和虚拟现实的机遇和挑战

智能时代下,人机交互和虚拟现实的机遇和挑战

多态(C++)

多态(C) 本文如果有错误或者不足的地方&#xff0c;希望各位大佬多多指点。 【本文目录】 1.多态的概念2.多态的定义及实现3.抽象类4.多态的原理5.单继承和多继承的虚函数表 1.多态的概念 多态的概念就是&#xff1a;多种形态 多态就是可以有多种的形态。不同的身份去实现同一…

【Leetcode 160】环形链表——双指针,细节讲解

题目 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&#…

RTSP/Onvif安防视频监控云平台EasyNVR重启后通道在线视频无法播放,接口报错502是什么原因?

EasyNVR安防视频云平台是旭帆科技TSINGSEE青犀旗下支持RTSP/Onvif协议接入的安防监控流媒体视频云平台。平台具备视频实时监控直播、云端录像、云存储、录像检索与回看、告警等视频能力&#xff0c;能对接入的视频流进行处理与多端分发&#xff0c;包括RTSP、RTMP、HTTP-FLV、W…

hypack如何采集多波束数据?(下)

多波束测量模块 1&#xff09;记录多波束和辅助传感器的数据&#xff1b; 2&#xff09;显示实时改正后的数据和数据质量信息。 ​编辑​ 测量准备 1&#xff09;设置大地测量参数和硬件设置&#xff1b; 2&#xff09;计划测线 计划测线是一定间距的平行线&#xff0c;…

微软联手清华,AI注释让文本到图像生成更符合人类偏好

获取本文论文原文PDF&#xff0c;请在公众号【AI论文解读】留言&#xff1a;论文解读 摘要 本研究展示了利用人类偏好数据集来精细调整文本到图像生成模型的潜力&#xff0c;增强了生成图像与文本提示之间的一致性。尽管取得了进展&#xff0c;现有的人类偏好数据集要么构建成…

掌控安全CTF-2024年5月擂台赛-WP(部分)

MISC ez_Misc 题目给了一个加密的压缩包和一个文本文档&#xff0c;首先我们先来看文本的内容&#xff0c;如下&#xff1a; 很容易看出&#xff0c;0宽隐写&#xff0c;用PuzzleSolver梭哈一下&#xff0c;发现了&#xff1a;Thi3 is n0t 2 hint 又在文本中发现一个特征&…

【2024】高校网络安全管理运维赛

比赛时间&#xff1a;2024-05-06 Re-easyre 基本的base64换表&#xff0c;用CyberChef解密 Re-babyre 进入主函数&#xff0c;发现输入四次 看一下就知道是大数求解 (当初写的时候差不多 不知道为什么第四个总是算错…) from z3 import *s Solver() # 设置一个解方程的类…

中心渗透Ⅱ

cs与msf权限传递以及mimikatz抓取win2012明文密码 使用Cobalt Strike抓取win2012明文密码&#xff0c;将会话传递到Metasploit Framework上 1.cs生成木马并使目标服务器中马 建立监听生成木马 2.抓取目标主机的明文密码 通过修改注册表来让Wdigest Auth保存明文口令 shell …

技术就绪度

技术就绪度&#xff08;Technology Readiness Level&#xff0c;简称TRL&#xff09;这个术语中的每个字符可以这样理解&#xff1a; 技术&#xff08;Technology&#xff09;&#xff1a;指的是正在研发或评估的具体的技术、工具、材料或方法。这可以是一套软件程序、一个物理…

一分钟揭秘面试官真实意图,稳拿offer的面试秘诀!

想要在面试中脱颖而出&#xff0c;顺利获得心仪的offer吗&#xff1f;那么&#xff0c;你需要了解面试官背后的潜台词。通过解析这些潜台词&#xff0c;你将能更准确地把握面试官的期望&#xff0c;并给出他们最喜欢的回答。下面&#xff0c;就让我们一起揭开这层神秘的面纱&am…

深入pandas:数据分析

目录 前言 第一点&#xff1a;导入模块 第二点&#xff1a;准备数据 第三点&#xff1a;简单的分析数据 第四点&#xff1a;【重点】数据透支 总结 前言 在数据分析与挖掘的领域&#xff0c;了解如何使用工具和方法来探索数据是至关重要的。本文将探讨如何利用Python中的…

C语言常用字符串处理函数

C语言中包含了很多对字符串处理的函数,要使用这些函数&#xff0c; 首先需要导入头文件#include <string.h> 1. strlen() -- 计算字符串长度 原型: size_t strlen(char const *string); 例: char *str "abcde"; size_t len strlen(str); // 结果为…

【DevOps】Elasticsearch在Ubuntu 20.04上的安装与配置:详细指南

目录 一、ES 简介 1、核心概念 2、工作原理 3、 优势 二、ES 在 Ubuntu 20.04 上的安装 1、安装 Java 2、下载 ES 安装包 3、创建 ES 用户 4 、解压安装包 5、 配置 ES 6、 启动 ES 7、验证安装 三、ES 常用命令 1、创建索引 2、 插入文档 3、查询文档 四、ES…