首页 > 编程笔记 > C++笔记 阅读:22

C++类模板的用法(附带实例)

通义灵码
C++ 中的函数模板代表了一系列函数,它们以统一的算法流程处理不同的数据类型。然而,函数模板仅定义了算法处理过程,而不保留算法执行过程中的数据。

例如,算法无法记住上一次调用的结果,也无法为下一次调用保留中间数据。为了解决这个问题,我们可以将算法封装在类中,使用成员变量来维护状态,并通过成员函数实现算法逻辑。

同样,C++ 允许类模板化,通过类型参数来处理多种数据类型。这样,类模板不仅可以像函数模板一样提供灵活性和通用性,还可以通过成员变量维护状态信息。

类模板的定义形式与函数模板类似,其语法格式如下:
  1. template <typename 标识符1, typename 标识符2...>
  2. class 类名
  3. {
  4. // 类的定义
  5. };
其中,template 关键字表示接下来的语句将定义一个模板。typename 所定义的标识符实际上是类模板的类型参数,可以是一个,也可以是多个。因为类模板定义的只是一个模板,所以类型参数只是代表一种抽象的数据类型,我们可以把它当作数据类型在类的定义中使用,例如,可以用它定义成员变量,也可以用作函数返回值或者参数的数据类型。

我们可以这样定义一个比较两个数据大小的类模板,示例代码如下:
  1. // 定义一个用于比较两个数据大小的类模板
  2. template <typename T> // T 是类模板的类型参数
  3. class compare
  4. {
  5. public:
  6. // 构造函数,使用 T 做参数类型,实际上它相当于一个函数模板
  7. compare(const T& a, const T& b)
  8. : m_a(a), m_b(b)
  9. {}
  10.  
  11. // 比较类的接口函数
  12. public:
  13. // 返回两个数中的较小值,使用 T 作为返回值类型
  14. T min()
  15. {
  16. return m_a > m_b ? m_b : m_a;
  17. }
  18. // 返回两个数中的较大值
  19. T max()
  20. {
  21. return m_a > m_b ? m_a : m_b;
  22. }
  23. // 类模板的成员变量,使用 T 作为它的数据类型
  24. private:
  25. T m_a;
  26. T m_b;
  27. };
在这段代码中,定义了一个用于比较两个数据大小的类模板 compare<T>。这个类模板拥有一个类型参数 T,这表示在使用这个类模板时,我们需要根据所比较数据的类型,在类名之后的“<>”内指定具体的数据类型,这样类模板才能根据实际的类型参数进行实例化,生成相应版本的模板类,以适应各种类型数据的比较。

例如:
  1. // 要比较两个整型数的大小
  2. // 使用 int 作为类模板的实际类型参数
  3. compare<int> cmpint(2,3); // 定义用于比较两个 int 数据的 compare 对象
  4. // 调用 compare<T> 的成员函数进行比较
  5. cout << cmpint.max() << "大于或等于" << cmpint.min() << endl;
  6.  
  7. // 要比较两个字符串的大小
  8. // 使用 string 作为类模板的实际类型参数
  9. compare<string> cmpstr("good","afternoon");
  10. cout << cmpstr.max() << "大于或等于" << cmpstr.min() << endl;
在这段代码中,我们要比较两个整型数,所以首先使用 int 数据类型作为类模板 compare<T> 的实际类型参数,将其实例化后得到一个新的模板类 compare<int>,这个模板类就可以完成两个 int 类型数据的比较。

这里所谓的实例化,就是用类模板的实际类型参数替换掉类模板中的类型参数,得到一个针对特定类型的模板类。例如,使用 int 对 compare<T> 类模板实例化后得到的模板类就是:
  1. // 使用实际类型参数 int 替换形式类型参数 T,得到实例化后的 compare<int>类
  2. class compare
  3. {
  4. public:
  5. compare(const int& a, const int& b)
  6. : m_a(a), m_b(b)
  7. {}
  8.  
  9. // 比较类的接口函数
  10. public:
  11. int min()
  12. {
  13. return m_a > m_b ? m_b : m_a;
  14. }
  15. // ...
  16. private:
  17. int m_a;
  18. int m_b;
  19. };
实例化之后的 compare<int> 类,我们可以将它当作一个普通的类来使用,使用它定义对象后,便可以调用该对象的成员函数来完成对两个整型数的比较。同样,使用 string 数据类型实例化 compare<T>类模板,可以得到模板类 compare<string>,从而用它比较两个字符串的大小。

以此类推,compare<T> 类模板还可以根据其他更多数据类型进行实例化,用于比较相应类型数据的两个数的大小,以此实现算法的通用性。

无论是函数模板还是类模板,它们的意义都是将算法和具体的数据类型分离。在定义时使用类型参数代表数据类型,而在使用时用实际的数据类型取代类型参数,使得算法适用于不同的数据类型,以实现算法的通用性。这使得程序员可以用一个模板处理各种数据类型,而无须为处理多种数据类型创建多个重载版本,一劳永逸地解决了算法适应不同数据类型的问题。

标准模板库 STL 正是基于 C++ 的模板机制构建起来的,其名字中的 T(template)代表模板,这也充分体现了 STL 的通用性。

相关文章