C++的类模板及特化

发布于 2021-09-04 08:55

嵌入式情报局
集单片机与linux于一身的技术号,深漂三年仍成功上岸研究生,这里不仅有技术还有故事,只为分享全面的嵌入式知识和深度的职场趣事,主要话题有:C/C++、数据结构与算法、MCU、嵌入式Linux 和物联网技术等,期待大家的持续!
132篇原创内容
大家好,我是情报小哥!

01

类模板

前面跟大家讲解了一下函数模板,我们知道函数模板说白了就是把函数体进行了统一抽象和类型参数化,以适配不同的函数调用,最终在编译的时候生成对应的函数进行处理。
基于这样的想法,其实相似的东西都可以交给编译器来实现。
这样也在一定程度上增加了代码的集成度和复用程度。
那么在C++中除了函数模板以外还有一类常用的模板类型-类模板。基本上构建一些基础库都会使用到类模板,像在stl库中有着大量的类模板。

02

类模板示例

那今天我们就来聊聊类模板。

首先来个简单的例子,看看类模板的基本语法:

1#include<cstdio>
2#include<iostream>
3using namespace std;
4
5//类模板
6template<typename Ty>
7class Calc
8
{
9public:
10
11    Ty Add(Ty param1 ,Ty param2)
12    {
13        return(param1 + param2);
14    }
15
16    Ty Sub(Ty param1 ,Ty param2);
17};
18
19template<typename Ty>  //须声明
20Ty Calc<Ty>::Sub(Ty param1 ,Ty param2) //函数外定义,需要类后面指定模板参数
21
22{
23
24    return(param1 - param2);
25}
26
27int main(void)
28{
29    Calc<int> calc1; //定义对象需指定模板参数类型
30
31
32    cout<<"templateint Add: "<<calc1.Add(10,5)<<endl;
33    cout<<"templateint Sub: "<<calc1.Sub(10,5)<<endl;
34
35    Calc<float> calc2; //定义对象需指定模板参数类型
36
37
38    cout<<"templatefloat Add: "<<calc2.Add(10.2,5.1)<<endl;
39    cout<<"templatefloat Sub: "<<calc2.Sub(10.2,5.1)<<endl;
40
41    return 1
42}
上面的代码把整个类就模板化,类型参数化了。而类作为是C++的标签,以后便可以支持多种数据类型,而把更多的精力放到类的功能实现上来,如下是输出结果 : 
其实类模板与函数模板一样也不是什么高大上的东西,编译器识别到了相应的数据类型以后便会进行模板函数体的替换,从而生成不同类型的新类,再进行最终编译、链接。
这些工作都交给了编译器,自然代码量会少很多,不过相应的语法也就更加的复杂,
所以回想一下C语言,C语言算是目前热门语言中语法非常简单的一门语言了,所以相比C++在实现相应的设计上需要更多的代码,比如用C语言实现面向对象的继承等等特性,C++语言已经在语法上把这些特性在编译器中跟我们实现好了,我们唯一要做的就是遵循C++语法,所以C++相对C而言处于跟上层一点的语言。

03

类模板的特化

当模板不能很好的处理某些数据类型的时候,我们就可以把该类型的处理过程进行特化。其实也很好理解,模板相当于模具,能够产生非常多的模型,而我们对其中某一个或者某一类模型的统一实现不是很满意,这时候我们想把他们单独拧出来重新定义实现,这个过程就是特化。
下面了解一下类模板特化的例子:
 1#include<cstdio>
2#include<iostream>
3using namespace std;
4
5//类模板
6template<typename Ty>
7class Calc
8
{
9public:
10
11    Ty Add(Ty param1 ,Ty param2)
12    {
13        return(param1 + param2);
14    }
15
16    Ty Sub(Ty param1 ,Ty param2);
17};
18
19template<typename Ty>  //须声明
20Ty Calc<Ty>::Sub(Ty param1 ,Ty param2) //函数外定义,需要类后面指定模板参数
21
22{
23
24    return(param1 - param2);
25}
26
27//类模板的特化
28template<>
29class Calc<float>
30
{
31public:
32
33    float Add(float param1 ,float param2)
34    {
35        cout<<"special Add template"<<endl;
36        return(param1 + param2);
37    }
38
39    float Sub(float param1 ,float param2);
40};
41
42float Calc<float>::Sub(float param1 ,float param2) 
43{
44    cout<<"special Sub template"<<endl;
45    return(param1 - param2);
46}
47
48int main(void)
49{
50    Calc<int> calc1; //定义对象需指定模板参数类型
51
52    cout<<"template int Add: "<<calc1.Add(10,5)<<endl;
53    cout<<"template int Sub: "<<calc1.Sub(10,5)<<endl;
54
55    Calc<float> calc2; //优先会选择匹配特化模板
56
57    cout<<"template float Add: "<<calc2.Add(10.2,5.1)<<endl;
58    cout<<"template float Sub: "<<calc2.Sub(10.2,5.1)<<endl;
59
60    return 1
61}
上面的小例子中直接把模板中的float参数类型拧出来重新定义了其具体的实现,如下结果可以看出,在具体调用的过程中优先会调用特化的模板类:

这样的特化处理有什么用呢?
特化主要是让类模板在不过度损伤代码复用性而使得类更加灵活,当我们构造了一个类模板或者正在使用了一个现成的类模板,而此时其对于相关参数的类型处理并不是非常的好用,需要进行改进,那么我们就可以把该类模板进行相应参数类型特化来进行改进,甚至还能够对特化类进行继承,形成一个全新的类来使用。

最  后 


嵌入式情报局
集单片机与linux于一身的技术号,深漂三年仍成功上岸研究生,这里不仅有技术还有故事,只为分享全面的嵌入式知识和深度的职场趣事,主要话题有:C/C++、数据结构与算法、MCU、嵌入式Linux 和物联网技术等,期待大家的持续!
132篇原创内容

☞ 专辑|Linux应用程序编程大全

☞ 专辑|学点网络知识

☞ 专辑|手撕C语言

☞ 专辑|手撕C++语言

☞ 专辑|经验分享

☞ 专辑|从单片机到Linux

☞ 专辑|电能控制技术

本文来自网络或网友投稿,如有侵犯您的权益,请发邮件至:aisoutu@outlook.com 我们将第一时间删除。

相关素材