C++初阶 模版进阶
一.非类型模版参数模板参数分类类型形参与非类型形参。类型形参即出现在模板参数列表中跟在class或者typename之类的参数类型名称。非类型形参就是用一个常量作为类(函数)模板的一个参数在类(函数)模板中可将该参数当成常量来使用。类型模版参数这里的 T 代表一种类型比如 int、double、char。非类型模版参数这里的 N 不是类型而是一个整数常量。这里 10、20 就是非类型模板参数。注意Array10 和 Array20 是两个不同的类型。常见用途是固定容量数组T 是类型模板参数表示数组元素类型。N 是非类型模板参数表示数组大小。非类型模板参数必须是编译期常量:正确写法:注意: 浮点数、类对象以及字符串是不允许作为非类型模板参数的二.模版的特化1.概念通常情况下使用模板可以实现一些与类型无关的代码但对于一些特殊类型的可能会得到一些错误的结果需要特殊处理对于都没问题但是有时候某个类型需要特殊处理如果直接:比较的是地址而不是字符串内容。这时候就需要对 char* 单独处理。2.函数模版特化函数模板的特化步骤1. 必须要先有一个基础的函数模板2. 关键字template后面接一对空的尖括号3. 函数名后跟一对尖括号尖括号中指定需要特化的类型4. 函数形参表: 必须要和模板函数的基础参数类型完全相同如果不同编译器可能会报一些奇怪的错误。特化后:输出: 1注意一般情况下如果函数模板遇到不能处理或者处理有误的类型为了实现简单通常都是将该函数直接给出。再保留原模版编译器会优先匹配:不会去实例化模板。3.类模版特化全特化普通模版专门针对 int输出: 普通模板int特化版本这里已经把所有模板参数都确定了所以叫全特化双参数类模板都属于普通模板偏特化情况1固定一个参数输出: 第二个参数为int这里T1 仍然可以变化都能匹配。因此只固定了一部分参数。叫偏特化情况2固定第一个参数输出: 第一个参数为int指针偏特化输出: 普通版本指针版本指针版本引用偏特化输出:引用版本三.模板分离编译1.什么是模板分离编译一个程序项目由若干个源文件共同实现而每个源文件单独编译生成目标文件最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式2.模版分离编译模板的声明和定义不能像普通函数一样随便分开放在 .h 和 .cpp 里。因为模板不是普通代码它需要在编译期根据具体类型实例化。如果你把实现写到 .cpp然后在 main.cpp 里使用这时候可能会链接错误。原因是main.cpp 只看到了模板声明但看不到模板定义所以编译器无法在 main.cpp 中实例化出而 Stack.cpp 虽然有模板定义但它没有使用所以它也不会生成 Stackint::Push 的具体代码。最后链接时就会报也就是找不到函数实现。3.解决方法1.声明和定义都放在头文件里或者类内声明类外定义但都写在 .h 里这样 main.cpp 包含头文件后既能看到声明也能看到定义就可以实例化模板。2.显式实例化如果你明确知道只会用某几个类型比如只用 int 和 double可以这样写。这样可以但如果你用就不行因为 .cpp 里没有显式实例化四.模板总结优点:1. 模板复用了代码节省资源更快的迭代开发C的标准模板库(STL)因此而产生2. 增强了代码的灵活性缺陷:1. 模板会导致代码膨胀问题也会导致编译时间变长2. 出现模板编译错误时错误信息非常凌乱不易定位错误