0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C++中为什么需要函数模板、类模板?

FPGA之家 来源:嵌入式客栈 作者:嵌入式客栈 2021-03-12 14:31 次阅读

[导读] 最近使用C++做些编程,把日常遇到的些比较重要的概念总结分享一下。本文来分享一下模板类的原理,以及为什么需要模板类,使用时的基本要点。

为什么需要模板

比如需要设计一个描述点的类,大致很快可以写成这样:

class Point_F { public: /*默认传入参数为0,0*/ Point_F(float x0 = 0, float y0 = 0) :x(x0), y(y0) /*初始化列表*/ { } /*用const修饰函数,表示函数不会修改成员数据*/ float get_x() const { return x; } float get_y() const { return y; } private: /*一般会将数据放在私有区,以对外隐藏*/ float x; float y; };

可问题是,在有的场合这点的坐标系有可能不需要浮点,比如界面设计中点往往是整型表示即可,那此时就需要再设计一个整型成员类:

class Point_I { public: /*默认传入参数为0,0*/ Point_f(int x0 = 0, int y0 = 0) :x(x0), y(y0) /*初始化列表*/ { } /*用const修饰函数,表示函数不会修改成员数据*/ int get_x() const { return x; } int get_y() const { return y; } private: /*一般会将数据放在私有区,以对外隐藏*/ int x; int y; };

可是在应用代码中,往往发现对于不同数据成员的应用操作确实基本类似,而且应用代码往往这两种(甚至更多成员数据类型)都可能会同时用到,仅仅因为数据类型就需要笨笨的将原代码在改写一下,在现代高级语言中,这显然就比较机械了。

C++中有没有可能将不同成员数据类型但是其顶层逻辑相同的对象,设计为一个类呢?就比如:

C++模板编程正是为了解决这样的需求而设计的机制。该机制允许函数或类使用泛型类型(generic type)进行操作。从而,函数或类就可以处理许多不同的数据类型,而无需为每种数据类型重写相应的类或者函数。

怎么实现的呢?

这里又可以大致分这样三种情况:

函数模板(Function templates)

类模板(Class templates)

**成员模板(Member templates) **

函数模板

函数模板其基本语法范式为:

template 《class identifier》 function_declaration; template 《typename identifier》 function_declaration;

template 为模板关键字

《typename identifier》 、《class identifier》 定义函数参数泛型类型或函数体类变量泛型类型

比如:

#include 《iostream》 using namespace std; template 《typename T》 T max(T a, T b) { return a 》 b ? a : b ; }

又或者写成如下形式:

#include 《iostream》 using namespace std; template 《class T》 T max(T a, T b) { return a 》 b ? a : b ; }

那么或许有的朋友会任务关键字class就意味着自定义类,而typename则是基本数据类型,比如int,float等,这样理解其实是不对的,从C++编译器的角度template 《typename T》与template 《class T》其语义是一样的,都是泛型,用户在使用这个模板函数的时候,所传入的参数都既可以是基本数据类型,也可以是类名。

对于上面的代码,或许初使用的朋友还会问,是不是可以随便传入类,这有可能编译不过。为什么呢?你传入的类需要支持》操作符,如果对于某个类你想使用该函数,而本身不支持》操作符,则需要实现》操作符。

类模板

与函数模板类似,类内部成员数据或者函数的参数或变量会使用,模板关键字定义的泛型名。比如:

template 《typename T》 class Point_T { public: Point_T(T x0 = 0, T y0 = 0) :x(x0), y(y0) { } T get_x() const { return x; } T get_y() const { return y; } private: T x; T y; };

这小段代码就回答了之前提出的问题,可以支持不同数据类型的点。

int main() { Point_T《int》 p1(1, 2); Point_T《float》 p2(1.1f, 2.2f); cout 《《 p1.get_x() 《《 endl 《《 p1.get_y() 《《 endl; cout 《《 p2.get_x() 《《 endl 《《 p2.get_y() 《《 endl; }

以上述简单例子看,分别构造了整型点p1,以及浮点型点p2,那么究竟怎么做到的呢?为了理解得更清楚,这里将其关键汇编代码段拷贝下来简要看看:

Point_T《int》 p1(1, 2); 000C1D6C push 2 000C1D6E push 1 000C1D70 lea ecx,[p1] 000C1D73 call Point_T《int》::Point_T《int》 (0C11D1h) Point_T《float》 p2(1.1f, 2.2f); 000C1D78 push ecx 000C1D79 movss xmm0,dword ptr [__real@400ccccd (0C7B34h)] 000C1D81 movss dword ptr [esp],xmm0 000C1D86 push ecx 000C1D87 movss xmm0,dword ptr [__real@3f8ccccd (0C7B30h)] 000C1D8F movss dword ptr [esp],xmm0 000C1D94 lea ecx,[p2] 000C1D97 call Point_T《float》::Point_T《float》 (0C1064h)

可见编译器对不同类型参数实际上做了相应解析,相当于根据用户程序传入的参数编译出相应的多份代码。所以可以简单理解成编译器根据不同泛型实际参数类型生成了相应的处理代码。而前面所说的模板函数其原理也基本类似。

总结一下

通过些简单例子,梳理一下模板函数以及模板类的基本概念以及原理,理解了这两个概念,就比较容易理解成员模板。所谓泛型模板编程,其本质是编译器针对不同参数类型解析解析生成相应的处理代码。学会使用模板泛型编程你会发现你会少写很多代码,代码看起来会比较优雅,而其实操作起来也没有想象中那么难。

原文标题:什么是函数模板、类模板?怎么做到的?

文章出处:【微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 编程
    +关注

    关注

    88

    文章

    3615

    浏览量

    93710
  • 模板
    +关注

    关注

    0

    文章

    108

    浏览量

    20561
  • C++
    C++
    +关注

    关注

    22

    文章

    2108

    浏览量

    73636

原文标题:什么是函数模板、类模板?怎么做到的?

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    同样是函数,在CC++中有什么区别

    同样是函数,在 CC++ 中有什么区别? 第一个返回值。 C语言的函数可以不写返回值类型,编译器会默认为返回 int。 但是
    的头像 发表于 11-29 10:25 291次阅读

    图纸模板的文本变量

    “  文本变量和系统自带的内置变量,可以帮助工程师灵活、高效地配置标题栏的信息,而不用担心模板的文字对象被意外修改。   ” 文本变量的语法 文本变量以 ${VARIABLENAME} 的方式
    的头像 发表于 11-13 18:21 172次阅读
    图纸<b class='flag-5'>模板</b><b class='flag-5'>中</b>的文本变量

    A0到A4的图框只要一个图纸模板就搞定了?

    非常灵活的管理方式,只需要一个图纸模板就可以搞定不同尺寸的场景。   ” 图纸模板的组成 图纸模板是由以下基本对象组成的: 直线 矩形 文本(包括普通字符串以及文本变量,或者系统自带的
    的头像 发表于 11-13 18:13 294次阅读
    A0到A4的图框只要一个图纸<b class='flag-5'>模板</b>就搞定了?

    摩尔线程开源高性能线性代数模板库MUTLASS

    近日,摩尔线程宣布开源高性能线性代数模板库MUTLASS,以便开发者能够更高效针对摩尔线程全功能GPU的MUSA Core及Tensor Core等单元进行编程,加速基于国产GPU的算子开发以及算法创新。
    的头像 发表于 11-13 11:53 319次阅读

    手写图像模板匹配算法在OpenCV的实现

    OpenCV模板匹配是支持基于NCC相似度查找的,但是不是很好用,一个主要的原因是查找最大阈值,只能匹配一个,自己比对阈值,又导致无法正确设定阈值范围,所以问题很多。于是我重新写了纯Python版本的NCC图像模板匹配的代码
    的头像 发表于 11-11 10:12 241次阅读
    手写图像<b class='flag-5'>模板</b>匹配算法在OpenCV<b class='flag-5'>中</b>的实现

    使用C语言实现函数模板

      用C语言能不能实现一个通用的函数,既能完成整数的相加,又能完成浮点数的相加?
    的头像 发表于 11-09 11:38 385次阅读

    ostream在c++的用法

    ostream 是 C++ 标准库中一个非常重要的,它位于 头文件(实际上,更常见的是通过包含 头文件来间接包含 ,因为 包含了 和 )。 ostream 及其派生
    的头像 发表于 09-20 15:11 698次阅读

    OpenHarmony标准系统C++公共基础库案例:HelloWorld

    1、程序简介该程序是基于凌蒙派OpenHarmony-v3.2.1标准系统C++公共基础库的简单案例:HelloWorld。主要讲解C++公共基础库案例如何搭建和编译。2、程序解析
    的头像 发表于 08-13 08:23 519次阅读
    OpenHarmony标准系统<b class='flag-5'>C++</b>公共基础<b class='flag-5'>类</b>库案例:HelloWorld

    基于OpenHarmony标准系统的C++公共基础库案例:ThreadPoll

    安全的线程池功能。 ThreadPoll维护一个任务队列,一个线程组。开发者只需向任务队列中注册需要进行的任务,线程组执行任务队列的任务。 C++公共基础库的Thread头文件在
    发表于 08-12 11:42

    C++实现类似instanceof的方法

    函数,可实际上C++没有。但是别着急,其实C++中有两种简单的方法可以实现类似Java的instanceof的功能。 在
    的头像 发表于 07-18 10:16 582次阅读
    <b class='flag-5'>C++</b><b class='flag-5'>中</b>实现类似instanceof的方法

    CW32F003E4芯片入门学习:4.工程模板创建(使用例程或模板)

    模板路径:CW32F003_StandardPeripheralLib_V1.4ExamplesTemplate
    的头像 发表于 04-24 14:14 402次阅读
    CW32F003E4芯片入门学习:4.工程<b class='flag-5'>模板</b>创建(使用例程或<b class='flag-5'>模板</b>)

    鸿蒙OS开发实例:【Native C++

    使用DevEco Studio创建一个Native C++应用。应用采用Native C++模板,实现使用NAPI调用C标准库的功能。使用C
    的头像 发表于 04-14 11:43 2619次阅读
    鸿蒙OS开发实例:【Native <b class='flag-5'>C++</b>】

    Altium Designer与Gerber模板的导入指南

    我们在设计完成后,准备输出Gerber的时候,有时候想用自己的Gerber模板导入PCB进行编辑,那么是如何设置导入的呢?
    的头像 发表于 03-28 09:41 1337次阅读
    Altium Designer与Gerber<b class='flag-5'>模板</b>的导入指南

    C++简史:C++是如何开始的

    的 MISRA C++:2023 博客系列的第二部分。 在这篇博客,我们将深入探讨 C++ 的历史、编程语言多年来的发展历程以及它的下一步发展方向。
    的头像 发表于 01-11 09:00 588次阅读
    <b class='flag-5'>C++</b>简史:<b class='flag-5'>C++</b>是如何开始的

    使用Jenkins和单个模板部署多个Kubernetes组件

    在持续集成和部署,我们通常需要部署多个实例或组件到Kubernetes集群。通过Jenkins的管道脚本,我们可以自动化这个过程。在本文中,我将演示如何使用Jenkins Pipeline及单个
    的头像 发表于 01-02 11:40 764次阅读
    使用Jenkins和单个<b class='flag-5'>模板</b>部署多个Kubernetes组件