C++类模板的用法(附带实例)
C++ 中的函数模板代表了一系列函数,它们以统一的算法流程处理不同的数据类型。然而,函数模板仅定义了算法处理过程,而不保留算法执行过程中的数据。
例如,算法无法记住上一次调用的结果,也无法为下一次调用保留中间数据。为了解决这个问题,我们可以将算法封装在类中,使用成员变量来维护状态,并通过成员函数实现算法逻辑。
同样,C++ 允许类模板化,通过类型参数来处理多种数据类型。这样,类模板不仅可以像函数模板一样提供灵活性和通用性,还可以通过成员变量维护状态信息。
类模板的定义形式与函数模板类似,其语法格式如下:
其中,template 关键字表示接下来的语句将定义一个模板。typename 所定义的标识符实际上是类模板的类型参数,可以是一个,也可以是多个。因为类模板定义的只是一个模板,所以类型参数只是代表一种抽象的数据类型,我们可以把它当作数据类型在类的定义中使用,例如,可以用它定义成员变量,也可以用作函数返回值或者参数的数据类型。
我们可以这样定义一个比较两个数据大小的类模板,示例代码如下:
在这段代码中,定义了一个用于比较两个数据大小的类模板 compare<T>。这个类模板拥有一个类型参数 T,这表示在使用这个类模板时,我们需要根据所比较数据的类型,在类名之后的“<>”内指定具体的数据类型,这样类模板才能根据实际的类型参数进行实例化,生成相应版本的模板类,以适应各种类型数据的比较。
例如:
在这段代码中,我们要比较两个整型数,所以首先使用 int 数据类型作为类模板 compare<T> 的实际类型参数,将其实例化后得到一个新的模板类 compare<int>,这个模板类就可以完成两个 int 类型数据的比较。
这里所谓的实例化,就是用类模板的实际类型参数替换掉类模板中的类型参数,得到一个针对特定类型的模板类。例如,使用 int 对 compare<T> 类模板实例化后得到的模板类就是:
实例化之后的 compare<int> 类,我们可以将它当作一个普通的类来使用,使用它定义对象后,便可以调用该对象的成员函数来完成对两个整型数的比较。同样,使用 string 数据类型实例化 compare<T>类模板,可以得到模板类 compare<string>,从而用它比较两个字符串的大小。
以此类推,compare<T> 类模板还可以根据其他更多数据类型进行实例化,用于比较相应类型数据的两个数的大小,以此实现算法的通用性。
无论是函数模板还是类模板,它们的意义都是将算法和具体的数据类型分离。在定义时使用类型参数代表数据类型,而在使用时用实际的数据类型取代类型参数,使得算法适用于不同的数据类型,以实现算法的通用性。这使得程序员可以用一个模板处理各种数据类型,而无须为处理多种数据类型创建多个重载版本,一劳永逸地解决了算法适应不同数据类型的问题。
标准模板库 STL 正是基于 C++ 的模板机制构建起来的,其名字中的 T(template)代表模板,这也充分体现了 STL 的通用性。
例如,算法无法记住上一次调用的结果,也无法为下一次调用保留中间数据。为了解决这个问题,我们可以将算法封装在类中,使用成员变量来维护状态,并通过成员函数实现算法逻辑。
同样,C++ 允许类模板化,通过类型参数来处理多种数据类型。这样,类模板不仅可以像函数模板一样提供灵活性和通用性,还可以通过成员变量维护状态信息。
类模板的定义形式与函数模板类似,其语法格式如下:
- template <typename 标识符1, typename 标识符2...>
- class 类名
- {
- // 类的定义
- };
我们可以这样定义一个比较两个数据大小的类模板,示例代码如下:
- // 定义一个用于比较两个数据大小的类模板
- template <typename T> // T 是类模板的类型参数
- class compare
- {
- public:
- // 构造函数,使用 T 做参数类型,实际上它相当于一个函数模板
- compare(const T& a, const T& b)
- : m_a(a), m_b(b)
- {}
- // 比较类的接口函数
- public:
- // 返回两个数中的较小值,使用 T 作为返回值类型
- T min()
- {
- return m_a > m_b ? m_b : m_a;
- }
- // 返回两个数中的较大值
- T max()
- {
- return m_a > m_b ? m_a : m_b;
- }
- // 类模板的成员变量,使用 T 作为它的数据类型
- private:
- T m_a;
- T m_b;
- };
例如:
- // 要比较两个整型数的大小
- // 使用 int 作为类模板的实际类型参数
- compare<int> cmpint(2,3); // 定义用于比较两个 int 数据的 compare 对象
- // 调用 compare<T> 的成员函数进行比较
- cout << cmpint.max() << "大于或等于" << cmpint.min() << endl;
- // 要比较两个字符串的大小
- // 使用 string 作为类模板的实际类型参数
- compare<string> cmpstr("good","afternoon");
- cout << cmpstr.max() << "大于或等于" << cmpstr.min() << endl;
这里所谓的实例化,就是用类模板的实际类型参数替换掉类模板中的类型参数,得到一个针对特定类型的模板类。例如,使用 int 对 compare<T> 类模板实例化后得到的模板类就是:
- // 使用实际类型参数 int 替换形式类型参数 T,得到实例化后的 compare<int>类
- class compare
- {
- public:
- compare(const int& a, const int& b)
- : m_a(a), m_b(b)
- {}
- // 比较类的接口函数
- public:
- int min()
- {
- return m_a > m_b ? m_b : m_a;
- }
- // ...
- private:
- int m_a;
- int m_b;
- };
以此类推,compare<T> 类模板还可以根据其他更多数据类型进行实例化,用于比较相应类型数据的两个数的大小,以此实现算法的通用性。
无论是函数模板还是类模板,它们的意义都是将算法和具体的数据类型分离。在定义时使用类型参数代表数据类型,而在使用时用实际的数据类型取代类型参数,使得算法适用于不同的数据类型,以实现算法的通用性。这使得程序员可以用一个模板处理各种数据类型,而无须为处理多种数据类型创建多个重载版本,一劳永逸地解决了算法适应不同数据类型的问题。
标准模板库 STL 正是基于 C++ 的模板机制构建起来的,其名字中的 T(template)代表模板,这也充分体现了 STL 的通用性。