第六弹:深入理解 C++ 模板机制及其应用

文章目录

      • 深入理解 C++ 模板机制及其应用
        • 1. 模板概述
        • 2. 函数模板
          • 2.1 函数模板的定义
          • 2.2 函数模板的调用
          • 2.3 函数模板与普通函数的区别
          • 2.4 类型模板参数与非类型模板参数
        • 3. 类模板
          • 3.1 类模板的定义
          • 3.2 类型模板参数与非类型模板参数
          • 3.3 类模板作为函数参数
          • 3.4 类模板作为派生类的基类
          • 3.5 类模板的实现
        • 4. 函数模板作为类模板的友元
        • 5. 模板的特化
          • 5.1 全特化
          • 5.2 偏特化
        • 6. 可变参数模板(Variadic Templates)
          • 6.1 可变参数函数模板
          • 6.2 可变参数类模板
        • 7. 模板的默认参数
        • 8. SFINAE(Substitution Failure Is Not An Error)
          • 使用 `std::enable_if` 进行类型限制
        • 9. 模板元编程(Template Metaprogramming)
        • 10. 类型萃取(Type Traits)
      • 总结


深入理解 C++ 模板机制及其应用

C++ 模板是实现泛型编程的重要工具,提供了代码复用、类型安全和编译期多态的能力。模板不仅让程序适应任意数据类型,还能够通过类和函数的参数化,使得编译器在编译阶段自动生成代码,减少开发过程中的重复工作。本文将详细探讨模板的各个知识点,展示如何通过模板机制编写高效、灵活的代码。


1. 模板概述

模板是一种参数化机制,允许开发者编写与具体类型无关的通用代码。C++ 模板主要有两种类型:函数模板类模板

  • 函数模板:用于创建可以处理多种类型参数的通用函数。
  • 类模板:用于定义数据结构和成员函数可以处理多种类型的通用类。

模板允许开发者编写逻辑结构相同但数据类型不同的代码,极大地提升了代码的复用性和可扩展性。


2. 函数模板
2.1 函数模板的定义

函数模板是为多个不同数据类型的函数创建的通用形式。通过 template (或 template ) 关键字,开发者可以定义一个接受不同类型参数的通用函数。例如:

// 函数模板的定义,T 是模板参数,可以代表任意类型
template <typename T>
T add(T a, T b) {
   
    return a + b;
}

该模板函数可以接受 intdouble 甚至 string 等不同类型的参数,编译器会根据传入参数的类型生成适当的函数版本。

2.2 函数模板的调用

调用模板函数与普通函数类似。编译器会根据传入参数的类型实例化模板,并生成相应的函数。代码如下:

int main() {
   
    cout << add(1, 5) << endl;            // 调用 int 类型的模板函数
    cout << add(1.2, 2.3) << endl;        // 调用 double 类型的模板函数
    cout << add(string("Hello"), string(" World")) << endl;  // 调用 string 类型的模板函数
}

模板函数的调用规则

  1. 若存在与模板函数同名的普通函数且匹配,优先调用普通函数。
  2. 若没有匹配的普通函数,编译器会实例化并调用模板函数。
  3. 若需要强制调用模板函数,可使用 add(1, 2) 这样的显示模板实例化语法。
2.3 函数模板与普通函数的区别
  • 模板函数不允许自动类型转换:函数模板要求参数的类型完全匹配,不能进行隐式类型转换。
  • 普通函数允许自动类型转换:普通函数在传递参数时可以自动执行类型转换。
template <typename T>
T myAdd(T a, T b) {
   
    return a + b;
}

int my_add(int a, int b) {
   
    return a + b;
}

int main() {
   
    int x = 3;
    char c = 'a';
    cout << my_add(x, c) << endl;  // 普通函数允许自动类型转换
    // cout << myAdd(x, c) << endl; // 错误:模板函数不允许自动类型转换
}
2.4 类型模板参数与非类型模板参数

模板除了可以接受类型参数外,还可以接受非类型参数。非类型模板参数的作用是在模板中传递一些固定的值,如数组的大小等。如下例所示,nmemb 是一个非类型模板参数:

// nmemb 是非类型模板参数,表示数组的大小
template <typename T, int nmemb>
void print_arr(T a[]) {
   
    for (int i = 0; i < nmemb; i++)
        cout << a[i] << " ";
    cout << endl;
}

int main() {
   
    int arr[5] = {
   1, 2, 3, 4, 5};
    print_arr<int, 5>(arr);  // 打印数组
}

3. 类模板
3.1 类模板的定义

类模板类似于函数模板,允许创建可以操作不同类型数据的类。通过 template ,开发者可以定义通用类,允许在类的不同实例中使用不同的数据类型。例如:

template <typename T>
class Arr {
   
public:
    Arr(int size = 0) {
   
        this->p = new T[size];
        this->size = size;
    }

    ~Arr() {
   
        delete

你可能感兴趣的:(C++,c++,函数模板,类模板)