C++中的泛型:什么是模板以及初学者如何使用它们

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C++中的泛型:为什么需要以及如何使用



你好,朋友!如果你刚开始学习C++,并且已经遇到了Generics(或模板)这个概念,那么这篇文章就是为你准备的。许多初学者害怕模板,认为它们复杂而神奇。实际上,一切都要简单得多。让我们来弄清楚这是什么,为什么需要它们,以及如何在实践中使用它们。



C++中的Generics(模板)是什么?



想象一下,你需要编写一个将两个数字相加的函数。你为int编写一个函数,为double编写另一个,为float编写第三个……你同意,这很繁琐,并且违反了DRY(Don't Repeat Yourself)原则。



这时模板(templates)就派上用场了。这是一种允许编写适用于任何数据类型的通用代码的机制。在C++中,这相当于其他语言(如Java或C#)中所谓的Generics。



模板不是具体的函数或类,而是一个“蓝图”或“配方”。编译器看到你使用带有int类型的模板时,会为int创建代码版本。如果你将其与double一起使用,编译器会为double创建版本。这称为模板实例化。



为什么需要模板?三个主要原因



1. 代码复用

不必为不同类型的数字编写10个函数,你只需编写一个通用函数。这节省了时间,减少了错误数量,并使代码更具可读性。



2. 类型安全

与宏(#define)或使用void*不同,模板由编译器检查。如果你尝试将不合适的类型传递给模板,编译器会在编译阶段报错,而不是在程序运行时。



3. 性能

模板不会增加运行时开销。编译器为每个具体类型创建优化后的代码,这段代码的运行速度与你手动编写的代码一样快。



如何使用模板:语法和示例



让我们看看两种主要的模板类型:函数模板和类模板。



函数模板

最简单的例子——一个找出两个值中最大值的函数。



#include <iostream>#include <string>

// 声明函数模板template <typename T>T max_value(T a, T b) { return (a > b) ? a : b;}

int main() { // 适用于 int std::cout << max_value(10, 20) << std::endl; // 输出: 20 // 适用于 double std::cout << max_value(3.14, 2.71) << std::endl; // 输出: 3.14 // 适用于字符串 std::cout << max_value(std::string("apple"), std::string("banana")) << std::endl; // 输出: banana return 0;}


关键字template告诉编译器:“注意,接下来是模板”。<typename T>是模板参数列表。T是类型的占位符名称,在调用函数时会被实际类型替换。可以使用class代替typename——没有区别。



重要提示:编译器会根据传递的参数自动推断你指的是哪种类型。这称为模板参数推导。但也可以显式指定类型:



std::cout << max_value<double>(10, 20.5) << std::endl; // 显式指定类型为 double


类模板

类模板允许创建通用的数据容器。经典例子是std::pair的简单模拟。



#include <iostream>#include <string>

// 模板

博客

书籍推荐