12.C++:模版进阶

目录

一、非类型模版参数

二、模版的特化

2.1、模版特化的概念

2.2、函数模版特化的具体操作

2.3、类模版的特化

2.3.1、全特化

2.3.2、偏特化(半特化)

三、模版的分离编译

3.1、什么是分离编译

3.2、模版的分离编译

四、模版的优缺点


一、非类型模版参数

前面我们一直用的类型模版,其实模版还有非类型模版,而且还可以给缺省值

比如,在定义一个静态数组的时候,你一开始给了10个空间,但是如果要存放1000个数据呢?但是如果你给了1000个空间,那么如果只有10个数据呢,那是不是就空间浪费了。所以,模版还给了非类型模版,解决了这个问题

cpp 复制代码
template<size_t N = 10>
struct a
{
    int arr[N];
} 

Note:(1)该做法只支持整型变量,对于浮点型,类类型和字符串时不行的。

(2)非类型的模版参数必须在编译时就确定。(比如:不能取决于用户的输入)

二、模版的特化

2.1、模版特化的概念

通常情况下,模版可以解决与类型无关的通用代码,但是对于一些特殊类型的操作可能会导致一些错误的结果,这时候,就需要对特殊的类型进行特化处理

2.2、函数模版特化的具体操作

(1)首先,你必须有一个基础的函数模版

(2)然后在 template后面接上一对空的 <>

(3)函数名后面再跟一对尖括号,尖括号里面放想要特化的类型

(4)函数的形参表:必须要和模版函数的基础参数类型完全相同

cpp 复制代码
template<class T>
void print(const T& val, const T& x)
{
	std::cout << val << x << std::endl;
}
//特殊处理double类型
template<>
void print<double>(const double& val, const double& x)
{
	std::cout << val + x<< std::endl;
}

Note:经过主包的实验,缺省值不影响,只要参数顺序,类型对得上就行。这里还要注意指针的const 修饰哦!

2.3、类模版的特化

类模版的特化对内部成员不要求一致。

cpp 复制代码
template<typename T>
class Printer {
public:
    void print() {
        std::cout << "General template" << std::endl;
    }
};
// 特化版本 - 当 T 为 int 时的特殊实现
template<>
class Printer<int> {
public:
    void print() {
        std::cout << "Specialized for int" << std::endl;
    }
};

2.3.1、全特化

将模版参数列表中的所有参数全部特化

2.3.2、偏特化(半特化)

任何针对模版参数进一步进行条件限制设计的特化版本,且不在要求空的 <>。

Note:只有偏特化不要求空的 <>

cpp 复制代码
template<typename T>
class Container {
public:
    void describe() {
        std::cout << "General container for type T" << std::endl;
    }
};
// 偏特化 - 当T是指针类型时的特殊实现
template<typename T>
class Container<T*> {  // 注意:尖括号里有 T*
public:
    void describe() {
        std::cout << "Specialized container for pointer types" << std::endl;
    }
};

三、模版的分离编译

3.1、什么是分离编译

一个程序右若干个源文件共同实现,每个源文件生成的目标文件链接起来形成一个单一的可执行文件的过程就是分离编译模式。

3.2、模版的分离编译

在学习模版的时候,有一条规则:不要把模版分离编译,如果非要这么干,也必须保证声明和定义在同一个文件下!现在,我们就来探讨一下为什么。

首先要回顾一下相关概念:

预处理:展开头文件,条件编译,宏替换,删除注释......(.h /.cpp -> .i)

编译:检查语法,生成汇编代码 (.i -> .s)

汇编:把汇编代码转换为二进制机器码 (.s -> .o)

链接:合并生成可执行程序,链接在其他文件定义的函数等 (.o -> .out)

那么,为什么模版不能分离定义?

因为模版没有实例化!编译器不知道实例化成什么类型!所以就没有实际代码出现。

3.3、解决办法

显示实例化

cpp 复制代码
template<typename T>
MyClass<T>::MyClass(T v) : value(v) {}

template<typename T>
void MyClass<T>::print() {
    std::cout << "Value: " << value << std::endl;
}

// 显式实例化你需要的类型
template class MyClass<int>;      // 实例化int版本
template class MyClass<double>;   // 实例化double版本

Note:不推荐!这样就丧失了泛型编程的意义

所以还是建议大家老老实实的不要分离编译,把它们放在同一个文件中。

四、模版的优缺点

优点:写出更灵活,更通用的泛型代码

缺点:报错不准,有时难以查错;

代码膨胀,让编译出的程序更大

相关推荐
_MyFavorite_几秒前
JAVA重点基础、进阶知识及易错点总结(10)Map 接口(HashMap、LinkedHashMap、TreeMap)
java·开发语言
charlie11451419111 分钟前
通用GUI编程技术——Win32 原生编程实战(十六)——Visual Studio 资源编辑器使用指南
开发语言·c++·ide·学习·gui·visual studio·win32
DpHard35 分钟前
现代 C++ 中 push 接口为何提供 const T& 与 T&& 两个重载
c++
wheelmouse77881 小时前
网络排查基础与实战指南:Ping 与 Telnet
开发语言·网络·php
敲代码的嘎仔1 小时前
Java后端开发——真实面试汇总(持续更新)
java·开发语言·程序人生·面试·职场和发展·八股
U-52184F691 小时前
深度解析:从 Qt 的 Q_D 宏说起,C++ 工业级 SDK 是如何保证 ABI 稳定性的
数据库·c++·qt
迈巴赫车主2 小时前
蓝桥杯20560逃离高塔
java·开发语言·数据结构·算法·职场和发展·蓝桥杯
春日见2 小时前
E2E自驾规控30讲:导论
开发语言·驱动开发·git·matlab·计算机外设
wangchunting2 小时前
Jvm-垃圾收集器
java·开发语言·jvm
沐知全栈开发2 小时前
PHP Math: 精通PHP中的数学函数与应用
开发语言