【C++】模板template

       🔥🔥 欢迎来到小林的博客!!
      🛰️博客主页:✈️林 子
      🛰️博客专栏:✈️ C++
      🛰️社区 :✈️ 进步学堂
      🛰️欢迎关注:👍点赞🙌收藏✍️留言

目录

认识模板

模板是C++中泛型编程的基础,一个模板就是一个创建类或者函数的蓝图或者说是公式。

当使用一个vector这样的泛型类型时,或者find这样的泛型函数时,我们提供足够的信息,将蓝图转化成类或者函数。这种转化发生在编译时。

function template函数模板

比如我们想写一个swap函数来交换两个数的值,在C++中我们可以用函数重载来重载多个函数来实现对不同类型的交换。比如我们要交换int 和 double类型,那么仅仅重载一个 swap(int& x ,int& y)是不够的。还需要重载一个swap(double& x,double& y) 函数。 但如果我还想交换其他的类型,也要写出其他类型对应的函数重载。这样就显得十分麻烦。所以这时候我们就可以function template(函数模板) 来减少我们需要写的代码。

template<class T> //定义函数模板
void Swap(T& x, T& y) //T是模板参数,也就是你传入的参数
{T tmp = x;x = y; y = tmp;
}
int main()
{int i1 = 5, i2 = 10;double d1 = 5.5, d2 = 10.5;string str1 = "hello", str2 = "world";cout << "交换前:" << endl;cout << "i1 : " << i1 << " , i2 :" << i2 << endl;cout << "d1 : " << d1 << " , d2 :" << d2 << endl;cout << "str1 : " << str1 << " , str2 :" << str2 << endl;Swap(i1, i2);Swap(d1, d2);Swap(str1, str2);cout << "交换后:" << endl;cout << "i1 : " << i1 << " , i2 :" << i2 << endl;cout << "d1 : " << d1 << " , d2 :" << d2 << endl;cout << "str1 : " << str1 << " , str2 :" << str2 << endl;return 0;
}

代码运行结果:

在这里插入图片描述

我们写了一份代码,就可以交换所有类型,而不用频繁的去自己写函数重载。

class类模板

类模板是用来生成类的蓝图,与函数模板不同的是,编译器不能为类模板推断模板参数类型。为了使用类模板,我们必须在类名后面加<>中提供额外信息。

template <class T>
class Node
{
public:void fun(){cout << "T* : " << typeid(next).name() << endl;cout << "T : " << typeid(val).name() << endl;}
private:T* next;T val;
};int main()
{Node<int> ni;ni.fun();cout << endl;Node<double> nd;nd.fun();cout << endl;Node<char> nc;nc.fun();return 0;
}

运行结果:

在这里插入图片描述

此时我们就可以发现,你<>中传什么类型进去,那么你类中的T就是什么类型。这就大大的方便了我们的编码,如果没有模板,那么每个类型都要安插一个这样的类出来,是非常麻烦的。

模板特化

如果你想对不同的模板参数,做不同的处理,那么此时你可以用模板指定类型。比如你有一个正常的模板,但是当模板参数为double时想做一下特殊处理,那么我们可以再定义一个类型模板的类。这样再生成模板时会优先生成最匹配的那一项

//普通模板
template<class T>
class A
{
public:A(){cout << "T()" << endl; }
};//特化
template<>
class A<double>
{
public:A(){cout << "double()" << endl;}
};int main()
{A<int> ai;A<char> ac;A<double>ad;return 0;
}

我们来看看它们会调用哪些构造函数。

在这里插入图片描述

我们发现,当在其他模板参数类型时会调用T(),但是当模板参数为double时,调用的是double()。 这也就意味着当模板参数为double时,那么会优先选择最匹配的。这种行为被称为特化。

半特化(偏特化)

当你要传入的模板参数,一半需要自动推导,一半又需要自己定义时,可以使用半特化。

template<class T1,class T2>
class A
{
public:A(){cout << "A<T1,T2>" << endl; }
};template<class T1>
class A<T1,char>
{
public:A(){cout << "A<T1,char>" << endl;}
};int main()
{A<int,int> a1;A<double,char> a2;A<char,char>a3;return 0;
}

运行结果:

在这里插入图片描述

我们发现,只要一个模板参数对应,那么就会优先选择对应的那个。

模板原理

模板的原理其实就是根据你所传的模板参数,又给你自动生成了一个类。而这个过程在编译时发生。就比如如下这个代码。

template<class T1,class T2>
class A
{
public:T1 a;T2 b;
};int main()
{A<int,int> a1;A<double,char> a2;A<char,char>a3;return 0;
}

它在编译后实际上是这样的

class A
{
public:int a;int b;
};class A
{
public:double a;char b;
};class A
{
public:char a;char b;
};

会生成三个A类。分别对应的模板参数

A<int,int> a1;
A<double,char> a2;
A<char,char>a3;

当然,我们在编码的时候是无法用相同的类名的。但在编译时,会有类似于函数重载的机制(个人猜测)生成出多个类。

所以,函数模板的本质就是方便你编码。等编译时再为你自动生成你当初传入的模板参数时对应的类。也就是说,虽然表面上你写的代码减少了,但本质上需要的代码并没有减少。只是在编译时为你自动生成了。

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

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

相关文章

【使用群晖远程链接drive挂载电脑硬盘】

文章目录 前言1.群晖Synology Drive套件的安装1.1 安装Synology Drive套件1.2 设置Synology Drive套件1.3 局域网内电脑测试和使用 2.使用cpolar远程访问内网Synology Drive2.1 Cpolar云端设置2.2 Cpolar本地设置2.3 测试和使用 3. 结语 前言 群晖作为专业的数据存储中心&…

Intelij IDEA 配置Tomcat解决Application Server不显示的问题

今天搭建war工程时部署项目发现&#xff0c;IDEA的控制台没有Application Servers&#xff0c;在网上查了一下&#xff0c;总结几个比较好的解决方法&#xff0c;为了方便自己和其他人以后碰到相同的问题&#xff0c;不再浪费时间再次寻找解决办法。 Intelij IDEA 配置Tomcat时…

整理mongodb文档:索引

个人博客 整理mongodb文档:索引 个人博客&#xff0c;求关注&#xff0c;有问题的地方欢迎指出&#xff0c;觉得讲解的繁琐的也请指出 文章概叙 本文主要还是在shell下的操作。让大家了解下mongodb中index的用途&#xff0c;基本的索引的新增、查看、删除等&#xff0c;最后…

Tomcat 为什么要破坏 Java 双亲委派机制?

大家好&#xff0c;我是锋哥!&#xff01; 我们分为4个部分来探讨: 什么是类加载机制&#xff1f;什么是双亲委任模型&#xff1f;如何破坏双亲委任模型&#xff1f;Tomcat 的类加载器是怎么设计的&#xff1f; 我想&#xff0c;在研究tomcat 类加载之前&#xff0c;我们复习…

react实现模拟弹框遮罩的自定义hook

需求描述 点击按钮用于检测鼠标是否命中按钮 代码实现 import React from react; import {useState, useEffect, useRef} from react;// 封装一个hook用来检测当前点击事件是否在某个元素之外 function useClickOutSide(ref,cb) {useEffect(()>{const handleClickOutside…

【LVS-NAT配置】

配置 node1&#xff1a;128&#xff08;客户端&#xff09; node2&#xff1a;135&#xff08;调度器&#xff09; RS&#xff1a; node3&#xff1a;130 node4&#xff1a;132 node2添加网络适配器&#xff08;仅主机模式&#xff09; [rootnode2 ~]# nmtui[rootnode2 ~]#…

全新 – Amazon EC2 M1 Mac 实例

去年&#xff0c;在 re: Invent 2021 大会期间&#xff0c;我写了一篇博客文章&#xff0c;宣布推出 EC2 M1 Mac 实例的预览版。我知道你们当中许多人请求访问预览版&#xff0c;我们尽了最大努力&#xff0c;却无法让所有人满意。不过&#xff0c;大家现在已经无需等待了。我很…

虫情测报系统的工作原理及功能优势

KH-CQPest虫情测报系统能够在不对虫体造成任何破坏的情况下&#xff0c;无公害的杀死虫子&#xff0c;利用高倍显微镜和高清摄像头拍摄虫体照片&#xff0c;并将虫体照片发送到远端平台&#xff0c;让工作人员无需要到现场&#xff0c;通过平台就可以观察害虫的种类和数量&…

我能“C”——实用的调试技巧

什么是bug&#xff1f; 调试是什么&#xff1f;有多重要&#xff1f; debug和release的介绍。 windows环境调试介绍。 一些调试的实例。 如何写出好&#xff08;易于调试&#xff09;的代码。 编程常见的错误。 1.什么是bug&#xff1f; 世界上第一个bug是程序员赫柏发现的。 …

Android性能优化----执行时间优化

作者&#xff1a;lu人皆知 在APP做启动优化时&#xff0c;Application会做一些初始化的工作&#xff0c;但不要在Application中做耗时操作&#xff0c;然而有些初始化工作可能是很耗时的&#xff0c;那怎么办&#xff1f;初始化操作可以开启子线程来完成。 计算执行时间 常规…

Vue在页面输出JSON对象,测试接口可复制使用

效果图&#xff1a; 数据处理前&#xff1a; 数据处理后&#xff1a; 代码实现&#xff1a; HTML: <el-table height"600" :data"tableData" border style"width: 100%" tooltip-effect"dark" size"mini"><el-…

【vue3】固定上导航栏和左侧导航栏,只显示其他内容在主内容区域

实现思路&#xff1a; 在一个单独的vue组件文件中只写出上导航栏和左侧导航栏的内容将你想要展示的页面主内容写到单独的组件中在index.js写路由&#xff0c;将【想要展示的页面主内容的路由】作为【子路由】写在【只写出上导航栏和左侧导航栏的路由】的下面&#xff1b; 在el…