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:不推荐!这样就丧失了泛型编程的意义

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

四、模版的优缺点

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

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

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

相关推荐
sali-tec7 小时前
C# 基于halcon的视觉工作流-章54-N点标定
开发语言·图像处理·算法·计算机视觉·c#
娇娇yyyyyy7 小时前
C++11新特性基础知识点汇总
开发语言·c++·算法
CILMY237 小时前
【一问专栏】Python中is和==的区别详解
开发语言·python·is·==
书院门前细致的苹果7 小时前
深入理解 Java 多线程与线程池 —— 从原理到实战
java·开发语言
烟花落o7 小时前
指针深入第二弹--字符指针、数组指针、函数指针、函数指针数组、转移表的理解加运用
c语言·开发语言·笔记·vscode·算法
熊猫_豆豆7 小时前
嫦娥号地月轨道、环月(一个月)MATLAB仿真
开发语言·matlab
wjs20247 小时前
MongoDB Java:深入解析与应用实践
开发语言
散峰而望7 小时前
基本魔法语言数组 (二) (C语言)
c语言·开发语言·github·visual studio
Benny_Tang8 小时前
CSP-J/S 2025 游记
c++