模版的引出

场景 :我要实现一个支持不同类型的交换函数
在这里插入图片描述

虽然有了函数重载支持可以实现多功能函数但是写起来比较恶心。这就是写与类型有关的代码的坏处

那么能不能引出无关类型的编程呢?泛式编程由此引出
在CPP中
模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。
模板是创建泛型类或函数的蓝图或公式。库容器,比如迭代器和算法,都是泛型编程的例子,它们都使用了模板的概念。

模版格式

template
其中,template 表示 下面的内容是模板typename 暂时定义模板参数的类型(typename可以用class关键字代替)

实现原理

其实我们把那些重复的工作交给了编译器这些编译器都给你实现好了,我们不过是在乘凉罢了,这种重复的工作交给编译器来完成,提高了生产力。这个时代重复的工作基本都会设计相关的策略利用机器完成工作,这就是为何说世界是由懒人创造的

对于模版来说
在预处理阶段,编译器根据实际的参数类型就会推理到对应的函数
然后按需实例化生成对应对象的成员函数
在这里插入图片描述

模版的实例化

注意 :在模版实例化之前,模版既不是函数也不是类
(就像月饼模具不是月饼一样)
只有模版实例化之后,才能成为真正的函数,真正的类

模版的隐式实例化

#include <iostream>

// 定义一个简单的函数模板
template <typename T>
T max(T a, T b) {
    return (a > b) ? a : b;
}

int main() {
    // 隐式实例化 max<int>
    std::cout << max(3, 5) << std::endl;
    
    // 隐式实例化 max<double>
    std::cout << max(3.14, 2.71) << std::endl;
    
    return 0;
}

优点:只有在代码中实际使用了模板的特定类型时,编译器才会生成该类型的实例

缺点:模板参数推导必须一致,编辑器并不会自动隐式转化类型
因为如果传化错了,编辑可不背黑锅
编译器要求两个参数推导出的类型必须完全一致

template<class T>
T Add(const T& left, const T& right)
{
    return left + right;
}

int main()
{
    int a1 = 10;
    double d1 = 10.0;
    
    Add(a1, d1); // 编译错误!
}

虽然在这种情况下编辑器不会推导模版类型,但是只要我们显示指定类型就会进行隐式类型转化

Add<int>(a1, d1);   // 将d1转换为int
Add<double>(a1, d1); // 将a1转换为double

显示指定模版

很多stl的容器在定义的时候,就会使用显示实例化对于函数模板
在这里插入图片描述

//以下都是显示实例化
std::vector<int> arr1
std::vector<std::string> arr2

注意: 类模板中函数放在类外定义时,需要加模板参数列表
在这里插入图片描述

35行就说明模板参数列表,T表示任意类型,class 表示任意类型的集合36行的 Vector表示 该函数属于模板类“强调了这是一个模板类

在以前: vector就是类型,因为模板 :vector才表示类型。

非类型模版与模版的特例化

非类型模版

在这里插入图片描述

非类型模板
第11行, N的前缀是sizet 不以class或typename为名,这是一个非类型模板参数
作用:从339和340看出 这种非类型模版常数很好的解决了 define 把常量写死的情况

模版的特例化

针对某一个模板的一种特殊的类型,对着种类型做出不一样的处理,这就是模板的特例化
在这里插入图片描述
这里实现了对int类型的特化。
注意写法:template中不写,将特例化的模板放在函数的后面相对于一个显示指定的作用)
在这里插入图片描述

为何模版不可以声明和定义分开(介绍分离编译)

在项目中一般会把声明放在.h,把源文件放到cpp文件里
目的:为了方便维护

分离编译机制 :
1.预处理展开头文件,替换宏,删除注释,条件编译
2.编译检测语法,生成汇编代码(.T文件)
3.编码把汇编代码转为二进制码(.o文件)
4.链接将.o文件整合

分离编译,即不同的源文件是分开了编译的(头文件已经在预处理阶段展开,不参与编译)如图Func.cpp 和 text.cpp 就会进行分离编译,在链接时,如果模板的定义和声明是分开来的,图1text.cpp里给了参数想去实例化模板但是没找到定义(分离编译),因为此时模板不能实例化这其实是模板的特性(模板在没实例化的时候不是类也不是函数,相当于一个模具)没有实例化,就没有地址在链接的时候就链接不上了

在这里插入图片描述

总结

模板的好处:有利于代码的复用,和灵活性,模板是引出STI库的关键

坏处: debug报错的时候很难定位错误(深有体会)
导致代码运行时间变长(模板要推类型)寻致代码膨胀,下图传不同类型的节点,一直会生成新的实例在这里插入图片描述

模版虽好,请勿滥用!!!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐