C++(模板)



在C++中,模板是泛型编程的重要工具,用于编写通用和可重用的代码。模板主要有两种类型:函数模板和类模板。



1. 函数模板(Function Templates)

函数模板允许你定义一个函数,其操作可以应用于不同的数据类型。它们可以在编译时生成多个版本的函数,以适应不同的数据类型。

1.1 基本语法:

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

这里,template <typename T> 定义了一个模板,其中 T 是一个类型参数。max 函数可以接受任意类型的参数,只要这两个参数的类型相同。

1.2 使用示例:

int main() {
    cout << max(10, 20) << endl;    // 使用int
    cout << max(10.5, 20.5) << endl; // 使用double
    return 0;
}

C++编译器根据调用 max 函数时的参数类型自动生成相应的函数版本。



2. 类模板(Class Templates)

类模板允许你定义一个类,其数据成员和成员函数可以依赖于模板参数。这使得类可以处理不同的数据类型。

2.1 基本语法:

template <typename T>
class Stack {
private:
    vector<T> elements;
public:
    void push(const T& element) {
        elements.push_back(element);
    }
    T pop() {
        if (elements.empty()) throw out_of_range("Stack<>::pop(): empty stack");
        T elem = elements.back();
        elements.pop_back();
        return elem;
    }
    bool empty() const {
        return elements.empty();
    }
};

这里,template <typename T> 定义了一个类模板,T 是一个类型参数。Stack 类可以处理任意类型的数据。

这段C++代码定义了一个模板类 Stack,实现了一个泛型栈的数据结构。让我们逐行解析这段代码:

1. 模板定义

template <typename T>
class Stack {
  • template <typename T>: 这行声明了一个模板类。T 是模板参数,表示栈中存储的元素类型。使用 typenameclass 都可以,typename 是更常用的习惯。

2. 私有成员

private:
    vector<T> elements;
  • private: 访问控制标记,表示下面的成员只能在类的内部访问。
  • vector<T> elements;: 这是一个 vector 容器,用于存储栈中的元素。vector 是一个标准库容器,T 是其元素类型,说明 Stack 类可以存储任何类型的元素。

3. 公有成员函数

push 函数
public:
    void push(const T& element) {
        elements.push_back(element);
    }
  • void push(const T& element): 这是一个公有成员函数,用于将元素 element 压入栈中。参数 const T& elementT 类型的常量引用,避免了拷贝操作,提高了效率。
  • elements.push_back(element);: 将元素添加到 vector 的末尾,这样实现了栈的“入栈”操作。
pop 函数
    T pop() {
        if (elements.empty()) throw out_of_range("Stack<>::pop(): empty stack");
        T elem = elements.back();
        elements.pop_back();
        return elem;
    }
  • T pop(): 这是一个公有成员函数,用于从栈中移除并返回栈顶元素。
  • if (elements.empty()) throw out_of_range("Stack<>::pop(): empty stack");: 如果栈为空,抛出 out_of_range 异常,避免在空栈上执行 pop 操作。
  • T elem = elements.back();: 获取栈顶的元素(即 vector 的最后一个元素)。
  • elements.pop_back();: 从 vector 中移除栈顶元素,执行“出栈”操作。
  • return elem;: 返回被移除的元素。
empty 函数
    bool empty() const {
        return elements.empty();
    }
  • bool empty() const: 这是一个公有成员函数,用于检查栈是否为空。const 关键字表明此函数不会修改类的成员数据。
  • return elements.empty();: empty()vector 的成员函数,返回 true 如果 vector 为空,false 如果 vector 里有元素。

总结

  • 数据成员elements 是一个 vector 容器,存储栈中的元素。
  • 成员函数
    • push(const T& element): 将元素压入栈中。
    • pop(): 移除并返回栈顶的元素,若栈为空则抛出异常。
    • empty() const: 检查栈是否为空。

这个 Stack 类模板允许你创建类型安全的栈,适用于任何数据类型。由于它是一个模板类,你可以用不同的类型实例化 Stack 类,如 Stack<int>Stack<double> 等。

2.2 使用示例:

int main() {
    Stack<int> intStack;
    intStack.push(1);
    intStack.push(2);
    cout << intStack.pop() << endl;  // 输出 2

    Stack<string> stringStack;
    stringStack.push("hello");
    stringStack.push("world");
    cout << stringStack.pop() << endl; // 输出 "world"

    return 0;
}

使用 Stack 模板类来创建和操作两个 Stack 对象:一个用于存储 int 类型的元素,另一个用于存储 string 类型的元素。

1. 创建 int 类型的栈对象

Stack<int> intStack;
  • Stack<int>: 这里使用 Stack 类模板创建一个类型为 int 的栈。intStack 是这个栈的实例,专门存储 int 类型的数据。

2. 入栈操作

intStack.push(1);
intStack.push(2);
  • intStack.push(1);: 将整数 1 压入 intStack 中。此时栈的状态是 [1]
  • intStack.push(2);: 将整数 2 压入栈中。此时栈的状态是 [1, 2]2 是栈顶元素。

3. 出栈操作及输出

cout << intStack.pop() << endl;  // 输出 2
  • intStack.pop(): 从 intStack 中移除栈顶的元素并返回它。此时栈顶元素 2 被移除,栈的状态变为 [1]。返回的值 2 被传递到 cout 中输出。
  • cout << intStack.pop() << endl;: 输出 2,并换行。

4. 创建 string 类型的栈对象

Stack<string> stringStack;
  • Stack<string>: 这里使用 Stack 类模板创建一个类型为 string 的栈。stringStack 是这个栈的实例,专门存储 string 类型的数据。

5. 入栈操作

stringStack.push("hello");
stringStack.push("world");
  • stringStack.push("hello");: 将字符串 "hello" 压入 stringStack 中。此时栈的状态是 ["hello"]
  • stringStack.push("world");: 将字符串 "world" 压入栈中。此时栈的状态是 ["hello", "world"]"world" 是栈顶元素。

6. 出栈操作及输出

cout << stringStack.pop() << endl; // 输出 "world"
  • stringStack.pop(): 从 stringStack 中移除栈顶的元素并返回它。此时栈顶元素 "world" 被移除,栈的状态变为 ["hello"]。返回的值 "world" 被传递到 cout 中输出。
  • cout << stringStack.pop() << endl;: 输出 "world",并换行。

7. 结束程序

return 0;
  • return 0;: 结束 main 函数并返回 0,表示程序成功结束。

总结

这段代码展示了如何使用 Stack 类模板来操作不同类型的栈对象:

  • 创建了一个 int 类型的栈 intStack,进行了元素的入栈和出栈操作,并输出了出栈的结果。
  • 创建了一个 string 类型的栈 stringStack,进行了元素的入栈和出栈操作,并输出了出栈的结果。

Stack 类模板的使用使得栈可以存储不同类型的数据,并且所有操作都是类型安全的。



3. 模板的特性

  1. 模板特化(Template Specialization)

    • 全特化:为特定类型提供特定实现。

      template <>
      class Stack<bool> {
          // 特化版本的实现
      };
      
    • 偏特化:为模板参数的某些组合提供特定实现。

      template <typename T>
      class Pair<T, T> {
          // 特化版本的实现
      };
      
  2. 非类型模板参数
    模板参数不仅可以是类型,也可以是常量值。

    template <int size>
    class Array {
        int arr[size];
    };
    
  3. 模板递归
    可以在模板中进行递归定义,用于编写复杂的编译时计算。

模板机制提供了极大的灵活性和重用性,是C++语言强大的特性之一。



posted @   做梦当财神  阅读(81)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示