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 函数,展示了成员函数模板的灵活性。

相关推荐
m0_547486667 小时前
《数据结构与算法》全套PPT课件2026(中国海洋大学)
数据结构·算法
旖旎夜光7 小时前
LeetCode 904:水果成篮(滑动窗口) —— 题解
数据结构·c++·算法·leetcode·滑动窗口
怪奇云呼军7 小时前
G.711、Opus 和重采样会拖慢识别吗?闪电智能VoiceAgent 的音频入口怎么选
java·人工智能·python·算法·云计算·音视频
乐观勇敢坚强的老彭9 小时前
C++ 竞赛常用算法模板速查表
开发语言·c++·算法
高洁019 小时前
工信部教考中心证书
人工智能·深度学习·算法·机器学习·知识图谱
我变成萤火虫9 小时前
河南萌新联赛2026第(三)场:郑州轻工业大学
数据结构·c++·算法·贪心算法·stl·深度优先·哈希算法
Dr.kangder9 小时前
嵌入式面试总结(十九)——内存泄露
单片机·算法·面试·职场和发展·架构·硬件架构
Herbert_hwt9 小时前
【C语言基础】常量、选择结构与运算符全解析
c语言·开发语言·算法
Suxing910 小时前
C语言基础分享:从“租房”到“拆迁”,C语言动态内存管理
java·数据结构·算法
LuminousCPP10 小时前
单链表专题(四)-刷题复盘篇-LeetCode 138 随机链表复制|原地拷贝法突破复杂指针操作
数据结构·笔记·算法·leetcode·链表