• C++模板进阶


    模板的特化

    分全特化,偏特化(也叫半特化)
    非类型模板参数也是可以特化的

    使用场景:

    优先级队列中,正常情况,如果我们想要比较整形家族(例如int, char)的数据时,可以用模板来传参,就可以比较大小了。

    template<class T>
    struct Less
    {
    	bool operator()(const T& x,const T& y) const
    	{
    		return x < y;
    	}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    但是我想要在类里面比较较为复杂的类型时,比如日期类Date。传参就传了指针,那么,并不能达到我们比较日期的目的,所以我们需要对这个类型进行特殊化处理(特化)。

    template<>
    strcut Less<Data*>
    {
    	bool operator()(Data* x, Data* y) const
    	{
    		return *x < *y;
    	}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这里是类模板特化,还有函数模板特化

    模板的分离编译

    首先什么是分离编译?
    一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件连接起来形成单一的可执行文件的过程。

    假如有以下场景,模板的声明与定义分离开,在头文件中进行声明,源文件中完成定义:

    // a.h
    template<class T>
    T Add(const T& x, const T& y);
    
    // a.cpp
    template<class T>
    T Add(const T& x, const T& y)
    {
    	return x + y;
    }
    
    // test.cpp
    #include"a.h"
    int main()
    {
    	Add(1, 2);
    	Add(1.0, 2.0);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    但这样写可行吗?
    我们知道程序运行的步骤:

    a.h/a.cpp/test.cpp
    生成a.i,test.i文件
    生成a.s,test.s文件
    生成a.o,test.o文件
    预处理:删除注释,宏替换,头文件展开,条件编译
    编译:检查语法,生成汇编代码
    汇编:把汇编代码转化成机器码
    链接将多个.o文件合并形成文件a.out

    其实模板

    test.cpp中,编译它调用Add()函数时,编译器只知道有一个Add()函数的声明,编译器没有看到对Add模板函数的实例化,因此不会生成具体的加法函数。
    main.obj中调用的AddAdd,编译器在链接时才会找其地址,但是这两个函数没有实例化没有生成具体代码,因此链接时报错。

    在这里插入图片描述
    解决方法

    1. 将声明和定义放到一个文件 “xxx.hpp” 里面或者xxx.h,也是可以的。——推荐使用这种
    2. 模板定义的位置显式实例化。—— 这种方法不实用,不推荐使用

    那类模板呢?
    我们使用某个类都要调用它的构造函数,所以其实类模板和函数模板在这里是一样的。

    仿函数

    对于排序算法来说,我们需要对不同的对象进行比较就可能需要不同的比较函数,这样才能排序。然而C语言提供的解决方法就是回调函数函数指针,说实在的比较晦涩难懂罢。到了C++我们就选择使用仿函数来解决。

    看如下仿函数Less

    template<class T>
    struct Less
    {
    	bool operator()(const T& x,const T& y) const
    	{
    		return x < y;
    	}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    其实就是重载了( )这个运算符的一个类。

    模板的优劣

    复用了代码,减少重复工作,更加方便开发,STL也是因此而诞生的。
    增强了代码灵活性。

    导致了代码膨胀,虽然不用模板也要写这么多代码,但是容易误以为很少。也会导致代码运行时间增加(主要是模板实例化导致的)。
    出现模板编译错误时,报错会变得很多,不容易定位错误(雀食)。

  • 相关阅读:
    WWW2022|京东提出变分embedding学习框架VELF解决CTR预估冷启动问题
    vue2进阶学习知识汇总
    [附源码]计算机毕业设计springboot学生综合数据分析系统
    慧差\畸变 zemax示例
    BeanFactory、FactoryBean和ObjectFactory、ApplicationContext的入门理解
    农业温室智能监控系统方案,实现农业自动化的最后一步
    如何在Docker中列出容器
    Hadoop Distributed System (HDFS) 写入和读取流程
    go-carbon 2.2.7 版本发布, 轻量级、语义化、对开发者友好的Golang时间处理库
    【学习笔记】HQL
  • 原文地址:https://blog.csdn.net/qq_56044962/article/details/125984748