一.概念
1.泛型编程(Generic Programming)
在计算机科学中,是一种允许一个值取不同数据类型(所谓多态)的技术。这种编程风格强调使用泛型技术,旨在推出一种针对算法、数据结构和内存分配机制的分类方法,以及其他能够带来高度可重用性、模块化和可用性的软件工具。
泛型这个词并不是通用的,在不同的语言实现中,具有不同的命名。在Java/Kotlin/C#中称为泛型(Generics),在ML/Scala/Haskell中称为Parametric Polymorphism,而在C++中被叫做模板(Template),比如最负盛名的C++中的STL。
2.泛型编程的特点:
代码复用:泛型编程可以编写一次代码,适用于多种数据类型,减少了代码的重复编写。例如,对于容器类型的操作,使用泛型方法可以避免对不同数据类型重复编写相同的代码。
灵活性:泛型编程能够处理不同类型的数据,使得程序更加灵活和可扩展。通过使用泛型算法和模板,可以在程序中处理各种不同类型的数据,而无需为每种数据类型编写特定的代码。
性能优化:泛型编程在编译时生成特定类型的代码,可以在一定程度上提高程序的性能。这种性能优化是因为泛型代码在编译时可以根据具体的数据类型进行优化,从而避免了运行时类型转换的开销。
独立性:泛型算法独立于任何特定的容器类型,这使得它们可以在各种容器上工作,只要这些容器支持所需要的基本操作。这种独立性使得泛型算法更加灵活和可重用。
在泛型编程中,可以使用类型参数来声明泛型类型,如<T>,表示接收任意类型的输入参数。在调用泛型函数或类时,可以使用<>运算符来指定所需的类型参数。
泛型编程在软件开发中广泛应用,能够大大提高代码的灵活性和可扩展性,降低重复代码和错误,提高软件开发的效率和质量。
二.C++中的泛型编程
1.模板是泛型编程的一种重要思想,它允许开发者创建独立于任何特定类型的代码。
C++ STL(Standard Template Library)正是泛型编程的一个模版库。
序列式容器主要有:
list(双向链表)
deque(双端队列)
stack(栈)
queue(队列)
heap(堆)
priority_queue(优先队列)
slist(单向链表)
array(数组)
forward_list(正向链表)
关联式容器主要有:
set(有序集合)
multiset(多重有序集合)
map(映射)
multimap(多重映射)
此外,STL还提供了无序关联容器,也被称为哈希容器,主要包括:
unordered_set(哈希集合)
unordered_multiset(哈希多重集合)
unordered_map(哈希映射)
unordered_multimap(哈希多重映射)
这些容器各有特点,适用于不同的场景。
vector适用于需要动态调整大小且元素访问频繁的情况;
list适用于频繁进行插入和删除操作的情况;
set和map则适用于需要自动排序的场景。
2.函数模板:
函数模板是一种通用的函数定义,允许在函数体中使用参数的类型作为参数。通过函数模板,可以实现对不同类型的数据执行相同的操作,提供代码重用和类型安全。
函数模板的定义使用 template 关键字,后跟模板参数列表和函数原型。例如:
template <typename T>
T Add(T a, T b) {
return a + b;
}
在上述示例中,typename T 是函数模板的参数列表,表示类型参数。函数体内的 T 表示使用该类型参数进行操作。
函数模板的使用方式是在调用函数时,根据实参的类型自动推导出模板参数的具体类型。例如:
int result1 = Add(1, 2); // 调用 Add<int>(1, 2);
double result2 = Add(3.14, 2.5); // 调用 Add<double>(3.14, 2.5);
3.类模板:
类模板是一种通用的类定义,类的成员变量和成员函数的类型可以在类定义时使用模板参数。通过类模板,可以编写可以使用多种数据类型的通用类。
类模板的定义使用 template 关键字,在类定义中通过特定的模板参数表示类型参数。例如:
template <typename T>
class MyContainer {
private:
T* elements;
int size;
public:
MyContainer(int n) {
size = n;
elements = new T[size];
}
// 其他成员函数的定义...
};
在上述示例中,typename T 是类模板的参数列表,表示类型参数。类中的成员变量 T* elements 和 int size 使用了类型参数 T。