C++——模板(工作中建议不要主动写)

主要内容:

1. 模板 - 实现泛型编程

用途: 模板为我们提供了泛型编程的能力,允许我们编写可以处理多种数据类型的代码,而无需为每种类型都写一遍代码。利用模板,我们可以定义一个通用的算法或数据结构,然后在编译时根据实际需要,将模板中的类型参数替换成具体的类型,从而生成针对特定类型的代码。

关键点:

  • 类型参数: 使用 typenameclass 关键字声明类型参数,例如 typename T
  • 模板实例化: 编译器在遇到使用模板的代码时,会根据实际传入的类型参数生成具体的代码,这个过程称为模板实例化。
  • 函数查找优先级: 编译器在寻找可调用函数时,会优先寻找完全匹配的函数,如果没有找到,才会尝试使用模板生成匹配的函数。

代码示例:

cpp 复制代码
#include <iostream>

template <typename T>
T max(T a, T b) {
  return (a > b) ? a : b;
}

int main() {
  int a = 5, b = 10;
  std::cout << "Max of " << a << " and " << b << " is: " << max(a, b) << std::endl;

  double c = 3.14, d = 2.71;
  std::cout << "Max of " << c << " and " << d << " is: " << max(c, d) << std::endl;
  return 0;
}

讲解: 这个例子定义了一个通用的 max 函数模板,可以比较任意两种类型的值并返回较大的值。在 main 函数中,我们分别使用 intdouble 类型调用 max 函数,编译器会自动生成两个不同版本的 max 函数,分别处理 intdouble 类型。

2. 函数模板

格式:

cpp 复制代码
template<typename T1, typename T2, ..., typename Tn> 
函数返回类型 函数名称 (参数列表) {
  // 函数执行代码
  // 模板类型可以用在函数的任何位置,比如参数列表中的参数类型,返回值类型,执行部分
}

关键点:

  • 声明: 使用 template 关键字和尖括号 <> 声明模板参数列表。
  • 参数列表: 可以有多个模板参数,用逗号分隔。
  • 实例化: 编译器根据函数调用时的参数类型,自动进行模板实例化。

代码示例:

cpp 复制代码
#include <iostream>

template <typename T>
T add(T a, T b) {
  return a + b;
}

int main() {
  int x = 5, y = 10;
  std::cout << "Sum of " << x << " and " << y << " is: " << add(x, y) << std::endl;

  double p = 3.14, q = 2.71;
  std::cout << "Sum of " << p << " and " << q << " is: " << add(p, q) << std::endl;
  return 0;
}

讲解: 这个例子定义了一个通用的 add 函数模板,可以将任意两种相同类型的数值相加。编译器会根据调用 add 函数时传入的参数类型,自动生成相应的函数实例。

3. 类模板

格式:

cpp 复制代码
template<typename T1, typename T2, ..., typename Tn>
class 自定义类型名 {
  // 成员列表 (成员变量, 成员函数)
};

关键点:

  • 声明: 与函数模板类似,使用 template 关键字和尖括号 <> 声明模板参数列表。
  • 定义: 类模板的成员函数一般需要在类外定义,并在定义时也要带上模板参数列表。
  • 实例化: 通过指定具体的类型参数来实例化类模板,例如 MyClass<int> myObject;

代码示例:

cpp 复制代码
#include <iostream>

template <typename T>
class MyArray {
private:
  T* data;
  int size;

public:
  MyArray(int size) : size(size) {
    data = new T[size];
  }

  ~MyArray() {
    delete[] data;
  }

  void set(int index, T value) {
    data[index] = value;
  }

  T get(int index) {
    return data[index];
  }
};

int main() {
  MyArray<int> intArray(5);
  intArray.set(0, 10);
  std::cout << "Value at index 0: " << intArray.get(0) << std::endl;

  MyArray<double> doubleArray(3);
  doubleArray.set(1, 3.14);
  std::cout << "Value at index 1: " << doubleArray.get(1) << std::endl;
  return 0;
}

讲解: 这个例子定义了一个 MyArray 类模板,可以创建一个存储任意类型的数组。在 main 函数中,我们分别实例化了 MyArray<int>MyArray<double>,创建了存储 int 类型和 double 类型的数组。

4. 成员函数模板

关键点:

  • 定义: 类模板的成员函数也可以是模板函数,这意味着一个成员函数可以处理多种类型的参数。
  • 声明: 在类模板内部声明成员函数模板时,需要再次使用 template 关键字和尖括号 <> 声明模板参数列表。
  • 实例化: 在调用成员函数模板时,编译器会根据传入的参数类型自动进行实例化。

代码示例:

cpp 复制代码
#include <iostream>

template <typename T>
class MyContainer {
private:
  T value;

public:
  MyContainer(T value) : value(value) {}

  template <typename U>
  void printWith(U prefix) {
    std::cout << prefix << ": " << value << std::endl;
  }
};

int main() {
  MyContainer<int> intContainer(10);
  intContainer.printWith("Integer");

  MyContainer<double> doubleContainer(3.14);
  doubleContainer.printWith("Double");
  doubleContainer.printWith(123); // 可以传入不同类型的参数
  return 0;
}

讲解: 这个例子定义了一个 MyContainer 类模板,其中包含一个成员函数模板 printWith。这个函数可以接受任意类型的参数 prefix,并将其与容器的值一起打印出来。在 main 函数中,我们分别使用字符串和整数作为 prefix 参数调用 printWith 函数,展示了成员函数模板的灵活性。

相关推荐
MATLAB代码顾问2 分钟前
混合粒子群-模拟退火算法(HPSO-SA)求解作业车间调度问题——附MATLAB代码
算法·matlab·模拟退火算法
Felven7 分钟前
C. Prefix Min and Suffix Max
算法
加农炮手Jinx7 分钟前
LeetCode 26. Remove Duplicates from Sorted Array 题解
算法·leetcode·力扣
加农炮手Jinx8 分钟前
LeetCode 88. Merge Sorted Array 题解
算法·leetcode·力扣
格林威8 分钟前
线阵工业相机:如何计算线阵相机的行频(Line Rate)?公式+实例
开发语言·人工智能·数码相机·算法·计算机视觉·工业相机·线阵相机
yueyue54311 分钟前
透过现象看本质:以fast_lio架构的整套算法的局部避障改为TEB算法为例深度探讨——如何成为一个合格的算法架构师?
算法·架构
梨花爱跨境11 分钟前
红人视频×A10算法:亚马逊转化率与流量闭环实战
算法
阿Y加油吧15 分钟前
二刷 LeetCode:75. 颜色分类 & 31. 下一个排列 复盘笔记
笔记·算法·leetcode
风筝在晴天搁浅17 分钟前
LeetCode 378.有序矩阵中第K小的元素
算法·矩阵
qeen8742 分钟前
【算法笔记】简单贪心
c++·笔记·算法·贪心算法