首页 > 其他分享 >一种将函数模板定义和声明分开的方法

一种将函数模板定义和声明分开的方法

时间:2023-01-02 14:11:23浏览次数:37  
标签:定义 int 分开 ------ fun 模板 函数

   在 C++ 中为了操作简洁引入了函数模板。所谓的函数模板实际上是建立一个通用函数,其函数类型或形参类型不具体指定,用一个虚拟的类型来表达,这个通用函数就称为函数模板。

1、通用的写法

        函数模板不是一个具体的函数,编译器不能为其生成可执行代码。定义函数模板后只是一个对函数功能框架的描述,当它具体执行时,将根据传递的实际参数决定其功能。为了容易使用,一般通用的写法都是在头文件中直接定义函数模板,定义的同时也是声明该函数,供给其它文件包含调用。

 1 //------fun.h或fun.hpp------//
 2 #ifndef _FUN_H_
 3 #define _FUN_H_
 4 
 5 using namespace std;
 6 
 7 template<typename T>  
 8 void fun(int b, T c, T d) //定义函数模板 
 9 {
10   ......
11 }
12 
13 #endif

  对编译器而言,定义函数模板的时候,编译器并不会对它进行编译,因为它没有一个实体可用,编译器只看到了声明,只有模板被实例化后(用在特定的类型上),编译器才会根据具体的类型对模板进行编译。因此当在别的文件中调用该函数模板时,根据传递的实际参数决定其功能,这样编译器就可以在编译期间看到模板函数的定义并完成模板的实例化,如果在编译的时候,找不到模板函数的定义,就先不在这一次编译中实例化该模板函数。

2、问题的引出

        但是头文件中定义和使用函数模板时,碰到了一个这样的场景,即在函数模板中使用到了全局变量:

 1 //------fun.h或fun.hpp------//
 2 #ifndef _FUN_H_
 3 #define _FUN_H_
 4 
 5 using namespace std;
 6 int a; //定义全局变量
 7 template<typename T>  
 8 void fun(int b, T c, T d) //定义函数模板 
 9 {
10   ......
11   a = b;
12 }
13 
14 #endif

        因此碰到其它多个文件需要使用该函数模板时,都需要各自包含该函数模板的头文件,编译时就会出现“全局变量重复定义”的错误。

        尝试按照普通函数定义和声明分开的思路将函数模板的定义和声明分开:

        源文件:

1 //------fun.cpp------//   //错误做法
2 using namespace std;
3 int a; //定义全局变量
4 template<typename T> 
5 void fun(int b, T c, T d) //定义函数模板
6 {
7   ......
8   a = b;
9 }

​        头文件:

1 //------fun.h或fun.hpp------//   //错误做法
2 #ifndef _FUN_H_
3 #define _FUN_H_
4 
5 extern a;
6 template<typename T> void fun(int b, T c, T d); 
7 
8 #endif

​        经过尝试,按照普通函数的方式将函数模板的定义和声明分开,在其它文件中调用函数模板,编译时就会出现“找不到该函数定义”的错误。

        那么有没有办法将函数模板的定义和声明正确分开,提供给其它文件包含调用呢,答案肯定是有的。

3、问题的解决

        针对上述第2点所阐述的函数模板使用的这一场景,需要将函数模板的定义和声明分离开来,根据实际的应用,使用以下的做法可以很好的解决这一问题,编译和调用都没有问题。

        首先是源文件*.cpp的实现:

 1 //------fun.cpp------//
 2 using namespace std;
 3 int a; //定义全局变量
 4 template<typename T> 
 5 void fun(int b, T c, T d) //定义函数模板
 6 {
 7   ......
 8   a = b;
 9 }
10 
11 template void fun(int b, int c, int d);  //函数模板实例化,此时T被int替代 
12 template void fun(int b, char c, char d); //函数模板实例化,此时T被char替代 

        因此在源文件中操作有:

        (1)、定义需要使用的函数模板;

        (2)、在定义的函数模板后进行函数实例化操作,通过这样的方法实现具体的模板函数。

      

        接着是头文件*.h或者*.hpp的实现:

 1 //------fun.h或fun.hpp------//
 2 #ifndef _FUN_H_
 3 #define _FUN_H_
 4 
 5 extern a;
 6 template<typename T> void fun(int b, T c, T d); 
 7 extern template void fun(int b, int c, int d);
 8 extern template void fun(int b, char c, char d); 
 9 
10 #endif

        因此在头文件中需要的操作有:

        (1)、声明定义的函数模板;

        (2)、使用extern的方式声明实例化后的模板函数。

总结

        可见,将函数模板的定义和声明分开,需要额外在源文件中进行函数模板的实例化再在头文件中进行声明,多了一些步骤。在无特定的使用的场景中,还是建议将函数模板放在头文件中直接定义并调用;当然,如果碰到一些跨文件调用的特定场景,那么采用这种将函数模板的定义和声明分开的方法也是OK的。


 

更多技术内容和书籍资料获取敬请关注微信公众号“明解嵌入式”

 

标签:定义,int,分开,------,fun,模板,函数
From: https://www.cnblogs.com/Sharemaker/p/17019826.html

相关文章

  • 一种将函数模板定义和声明分开的方法
            在C++中为了操作简洁引入了函数模板。所谓的函数模板实际上是建立一个通用函数,其函数类型或形参类型不具体指定,用一个虚拟的类型来表达,这个通用函数就称......
  • 排序模板
    目录快速排序堆排序目的在于复习常见的排序题型和实现方式。快速排序时间复杂度:最坏情况为\(O\left(n^{2}\right)\);平均时间复杂度为\(O\left(n\log_{2}n\right)\);......
  • odoo10如何自定义自动生成单据编号
    1.在已有的model中穿件一个字段nameclassqingjiadan(models.Model):_name='qingjia.qingjiadan'name=fields.Char(string='编号',readonly=True)2.创建qingjia_app......
  • 前端大屏模板分享-可在线浏览
    1.前言站长以前介绍过这个开源项目,最近又有人在问,索性挂在Dotnet9网站上,方便大家在线浏览,先声明,模板来自下面的仓库:仓库名:大屏数据展示模板作者:lvyeyou开源协议:MIT仓库地址......
  • jsp自定义标签
    jsp自定义标签   需求:向浏览器输出当前客户的IP地址(只能使用jsp标签)1.自定义标签开发步骤    1. 编写一个普通的java类,继承SimpleTagSupport......
  • Django自定义分页器
    目录Django自定义分页器一、分页器思路二、自定义分页器的使用Django自定义分页器一、分页器思路分页器主要听处理逻辑代码最后很简单推导流程 1.queryset支持切片......
  • layui 注册模板--并且提示注册成功--太爽了
    <!doctypehtml><htmlclass="x-admin-sm"><head><metacharset="UTF-8"><title>后台登录-X-admin2.2</title><metaname="renderer"content="webkit|ie-comp......
  • Grafana模板
    Grafana模板ApacheJMeterDashboardusingCoreInfluxdbBackendListenerClientGrafana模板模板地址:https://grafana.com/grafana/dashboards?search=jmeterApacheJMete......
  • zabbix利用自带模板监控mysql常见问题
    先放出完整步骤:1,创建数据库监控用户mysql-uroot-prootGRANTUSAGEON*.*TO'mysqlcheck'@'localhost'IDENTIFIEDBY'mysqlcheck';FLUSHPRIVILEGES;注意:当出现错误:E......
  • Django模板层
    目录Django模板层一、关于模板语法二、模板层之标签二、自定义过滤器、标签三、模板的继承与导入四、模板层前期准备Django模板层一、关于模板语法针对需要加括号调用的......