c++模板 | Nobilta's Blog
0%

c++模板

模板是一个c++中很神奇的结构,合理使用模板可以大大减少代码量以及提高代码复用性,接下来记录一下模板的学习笔记。

函数模板

模板的基础使用很简单,而本质上当我们调用模板的时候不是直接调用了函数的模板,而是编译器通过模板生成了一个新的函数,直接上使用模板的绝对值的例子代码:

1
2
3
4
5
template <class T>//不使用class关键字也可以使用typename关键字template <typename T>,也叫模板参数表
T abs(T a)
{
return a>0?a:-a;
}

这其中有class/typename为函数的类型参数,T我的理解是相当于传递的函数形参。模板的基础中还有一个需要注意的点:只有能够进行函数中运算的类型,才能作为类型的参数,如果传递的类型参数为自定义类型,或者默认的运算符无法对它们进行操作,则需要我们先重载运算符再使用模板。

类的模板

和函数的模板差不多,类的模板也是通过使用模板生成一个我们需要的数据类型的类,比如我们可以这么写:

1
2
3
4
5
6
7
8
9
10
11
12
13
template <typename T>//T叫什么都行
class Base
{
private:
T num;
public:
T getnum();
}
template <typename T>
T Base<T>::getnum()
{
return num;
}

在每一处使用需要使用模板对象的时候,都应该加上template,其他和函数模板基本一样。

数组模板

在我们使用数组的时候,必须事先定义好数组的大小,这个大小是在编译的时候已经固定的,不能在运行的时候调整数组的大小。而在很多情况下,我们希望我们的数组可以动态的调整大小,在我们需要它储存更多数据时,进行动态的扩容(类似于stl中的vector),而数组模板就可以实现这个目的。
先看个例子:

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
template<class T>
class Array
{
private:
T* list;//用于储存数组的首地址
int size;//动态数组的大小
public:
Array(int sz = 10);//构造函数
{
assert(sz>=0)//sz为数组大小
size = sz;
list = new T[size];//动态分配size个T类型的空间
}
Array(const Array<T>&a)//复制构造函数,用于复制数组
{
size = a.size //复制前一个对象的数组大小
list = new T[size];//动态分配size个T类型的大小
for(int i = 0 ; i < size ; i++)//将前一个对象的所有元素复制过来
{
list[i] = a.list[i];
}
}
~Array();//析构函数
{
delete [] list;//释放空间
}
Array<T> &operator=(const Array<T> &rhs)//重载=
{
if(rhs != this)//如果两个对象不相等的话
{
delete [] list;//删除原数组,并复制新数组
size = rhs.size();
list = new list[size];
for(int i = 0 ; i < size ; i++)
list[i] = rhs.list[i];
}
return *this;//最后返回当前对象的引用
}
T & operator[](int i)//重载[]以便可以直接访问
{
assert(i>=0&&i<size);//检查数组是否越界
return list[i];//返回下标为n的元素
}
const T & operator[](int i) const//与上同,只不过这次返回的是常量类型的元素
{
assert(i>=0&&i<size);
return list[n];
}
operator T *()//返回数组的指针
{
return list;//返回对象中私有数组的首地址
}
operator const T*() const//返回静态指针
{
return list;
}
};
  • Q1:为什么有的函数返回值为引用类型(运算符重载函数)?
    W:因为重载的=,我们想要的效果是将这个值作为函数表达式中的左值,即可以直接操作,而如果不是引用类型,它只能做右值。(引用是对象的别名,所以可以通过引用修改对象的值)
  • Q2:为什么有的函数必须添加一个const类型?
  • W:比如指针,如果返回的是常指针,则我们只能通过这个指针读取动态数组中的元素,而不能通过这个指针对数组中的元素进行修改
    这样就基本实现了一个类似于vector的动态数组(当然vector要比这个简单的例子复杂很多了,毕竟正经的stl)模板是个很好用的c++特性,利用模板我们可以大大减少代码的重复量,增强代码的复用性(很多头文件中的函数的实现都是依赖于模板)
您的支持将鼓励我继续创作!