首页
社区
课程
招聘
[分享]C++基础十六-模板
2021-10-26 17:53 8123

[分享]C++基础十六-模板

2021-10-26 17:53
8123

泛型程序设计

泛型程序设计是一种算法在实现时不指定具体要操作的数据的类型的程序设计方法,能够减少重复代码的编写。所谓泛型,指的是算法只要实现一遍,就能适用于多种数据类型。

函数模板

C++ 中数据的值可以通过函数参数传递,在函数定义时数据的值是未知的,只有等到函数调用时接收了实参才能确定其值。这就是值的参数化。同理,数据的类型也可以通过参数来传递,在函数定义时可以不指明具体的数据类型,当发生函数调用时,编译器可以根据传入的实参自动推断数据类型。这就是类型的参数化。
所谓函数模板,实际上是建立一个通用函数,它所用到的数据的类型(包括返回值类型、形参类型、局部变量类型)可以不具体指定,而是用一个虚拟的类型来代替(实际上是用一个标识符来占位),等发生函数调用时再根据传入的实参来逆推出真正的类型。这个通用函数就称为函数模板。
为了交换不同类型的变量的值,可以通过函数重载定义名字相同、参数列表不同的函数,但从本质上看还是定义了功能相同、函数体相同的函数,只是数据的类型不同。通过函数模板,可以实现一个函数解决问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
using namespace std;
 
template<typename T> void Swap(T& NumberA, T& NumberB)
{
    T temp = NumberA;
    NumberA = NumberB;
    NumberB = temp;
}
 
int main()
{
    //交换 int 变量的值
    int n1 = 8;
    int n2 = 9;
    Swap(n1, n2);
    cout << "n1=" << n1 << " n2=" << n2 << endl;
 
    //交换 float 变量的值
    float f1 = 8.8;
    float f2 = 9.9;
    Swap(f1, f2);
    cout << "f1=" << f1 << " f2=" << f2 << endl;
 
    return 0;
}

template是定义函数模板的关键字,它后面紧跟尖括号<>,尖括号包围的是类型参数,typename是用来声明具体的类型参数的关键字,这里的类型参数就是T。从整体上看,template<typename T>被称为模板头,模板头中包含的类型参数可以用在函数定义的各个位置,包括返回值、形参列表和函数体。

类模板

C++ 还支持类模板,类模板的目的同样是将数据的类型参数化。函数模板中定义的类型参数可以用在函数声明和函数定义中,类模板中定义的类型参数可以用在类声明和类实现中。

1
2
3
4
template<typename 类型参数1,typename 类型参数2,...> class 类名
{
    //TODO:
};

类模板和函数模板都是以template 开头,后跟类型参数,类型参数不能为空,多个类型参数用逗号隔开。一但声明了类模板,就可以将类型参数用于类的成员函数和成员变量了。

使用类模板实现动态数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include <iostream>
using namespace std;
 
template<typename T> void Swap(T& NumberA, T& NumberB)
{
    T temp = NumberA;
    NumberA = NumberB;
    NumberB = temp;
}
 
template <typename T> class CArray
{
    int size; //数组元素的个数
    T* ptr; //指向动态分配的数组
public:
    CArray(int s = 0);  //s代表数组元素的个数
    CArray(CArray& a);
    ~CArray();
    T length();
    T& operator[](int i); //用以支持根据下标访问数组元素
    CArray& operator=(const CArray& a); //用于数组对象间的赋值
    void push_back(const T& v); //用于在数组尾部添加一个元素v
};
 
template<typename T>
T CArray<T>::length()
{
    return size;
}
 
template<typename T>
T& CArray<T>::operator[](int i)
{
    return ptr[i];
}
 
template<class T>
CArray<T>::CArray(int s) :size(s)
{
    if (s == 0)
    {
        ptr = NULL;
    }
    else
    {
        ptr = new T[s];
    }
}
 
template<class T>
CArray<T>::CArray(CArray& a)
{
    if (!a.ptr)
    {
        ptr = NULL;
        size = 0;
        return;
    }
    ptr = new T[a.size];
    memcpy(ptr, a.ptr, sizeof(T) * a.size);
    size = a.size;
}
 
template <class T>
CArray<T>::~CArray()
{
    if (ptr)
    {
        delete[] ptr;
    }
    size = 0;
}
 
template <class T>
CArray<T>& CArray<T>::operator=(const CArray& a)
{
    if (this == &a)
    {
        return *this;
    }
    if (a.ptr == NULL)
    {
        if (ptr)
        {
            delete[] ptr;
        }
        ptr = NULL;
        size = 0;
        return *this;
    }
    if (size < a.size)
    {
        if (ptr)
        {
            delete[] ptr;
        }
        ptr = new T[a.size];
    }
    memcpy(ptr, a.ptr, sizeof(T) * a.size);
    size = a.size;
    return *this;
}
 
template <class T>
void CArray<T>::push_back(const T& v)
{
    if (ptr)
    {
        T* tmpPtr = new T[size + 1]; //重新分配空间
        memcpy(tmpPtr, ptr, sizeof(T) * size); //拷贝原数组内容
        delete[] ptr;
        ptr = tmpPtr;
    }
    else
    {
        ptr = new T[1];
    }
    ptr[size++] = v;
}
 
int main()
{
    //交换 int 变量的值
    int n1 = 8;
    int n2 = 9;
    Swap(n1, n2);
    cout << "n1=" << n1 << " n2=" << n2 << endl;
 
    //交换 float 变量的值
    float f1 = 8.8;
    float f2 = 9.9;
    Swap(f1, f2);
    cout << "f1=" << f1 << " f2=" << f2 << endl;
 
    CArray<int> a;
    for (int i = 0; i < 6; ++i)
    {
        a.push_back(i);
    }
    for (int i = 0; i < a.length(); ++i)
    {
        cout << a[i] << " ";
    }
 
    return 0;
}

github:https://github.com/0I00II000I00I0I0

bilibili:https://space.bilibili.com/284022506


[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

收藏
点赞2
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回