注:博客中内容主要来自《狄泰软件学院》,博客仅当私人笔记使用。
测试环境:Ubuntu 10.10
GCC版本:9.2.0
一、思考
在C++中是否能够将泛型的思想应用于类?
stl标准库里广泛应用。
二、类模板
1) 一些类主要用于存储和组织数据元素
2) 类中数据组织的方式和数据元素的具体类型无关
3) 如:数组类,链表类,Stack类,Queue类,等
C++中将模板的思想应用于类,使得类的实现不关注数据元素的具体类型,而只关注类所需要实现的功能。
4) C++中的类模板
- 以相同的方式处理不同的类型
- 在类声明前使用template进行标识
- <typename T>用于说明类中使用的泛指类型T
template < typename T >
class Operator
{
public:
T op(T a, T b);
};
5) 类模板的应用(重点)
- 只能显示指定具体类型,无法自动推导
- 使用具体类型<Type>定义对象
Operator<int> op1;
Operator<string> op2;
int i = op1.op(1,2);
string s = op2.op("D.T.","Software");
7) 声明的泛指类型T可以出现在类模板的任意地方
8) 编译器对类模板的处理方式和函数模板相同
- 从类模板通过具体类型产生不同的类
- 在声明的地方对类模板代码本身进行编译
- 在使用的地方对参数替换后的代码进行编译
编程实验
类模板初探
58-1.cpp
#include <iostream>
#include <string>
using namespace std;
//第一次对类模板进行编译
template < typename T >
class Operator
{
public:
T add(T a, T b)
{
return a + b;
}
T minus(T a, T b)
{
return a - b;
}
T multiply(T a, T b)
{
return a * b;
}
T divide(T a, T b)
{
return a / b;
}
};
int main()
{
//第二次在使用的地方进行编译
Operator<int> op1;
cout << op1.add(1, 2) << endl;
//第二次首先编译这里构造函数
Operator<string> op2;
//第二次编译针对add函数(第二次编译也是分阶段编译,理解不冲突)
cout << op2.add("D.T.", "Software") << endl;
//第二次针对minus编译时,发现字符串没有相减操作,编译器报错!!有了添加的重载字符串减法函数,编译器匹配
cout << op2.minus("D.T", "Software") << endl; //两个字符串不能相减
return 0;
}
操作:
1) g++ 58-1.cpp -o 58-1.out编译错误:
58-1.cpp: In instantiation of ‘T Operator<T>::minus(T, T) [with T = std::basic_string<char>]’:
58-1.cpp:46:38: required from here
58-1.cpp:17:12: error: no match for ‘operator-’ (operand types are ‘std::basic_string<char>’ and ‘std::basic_string<char>’)
return a - b;
58-1.cpp:在实例化'T Operator<T>::minus(T, T) :
58-1.cpp:17:12: error: 没有匹配'operator-'
因为没有自定义字符串减法操作,导致找不到相应的匹配函数。
解决办法:
#include <iostream>
#include <string>
using namespace std;
//第一次对类模板进行编译
template < typename T >
class Operator
{
public:
T add(T a, T b)
{
return a + b;
}
T minus(T a, T b)
{
return a - b;
}
T multiply(T a, T b)
{
return a * b;
}
T divide(T a, T b)
{
return a / b;
}
};
//有这个函数编译器不报错
string operator-(string& l, string& r) //重载字符串相减,为了解决编译第二阶段错误
{
return "Minus"; //不为了实现功能
}
int main()
{
//第二次在使用的地方进行编译
Operator<int> op1;
cout << op1.add(1, 2) << endl;
//第二次首先编译这里构造函数
Operator<string> op2;
//第二次编译针对add函数(第二次编译也是分阶段编译,理解不冲突)
cout << op2.add("D.T.", "Software") << endl;
//第二次针对minus编译时,发现字符串没有相减操作,编译器报错!!有了添加的重载字符串减法函数,编译器匹配
cout << op2.minus("D.T", "Software") << endl; //两个字符串不能相减
return 0;
}
g++ 58-1.cpp -o 58-1.out编译正确,打印结果:
3
D.T.Software
Minus
9) 类模板的工程应用(工程中应用习惯)
- 类模板必须在头文件中定义
- 类模板不能分开实现在不同的文件中
- 类模板外部定义的成员函数需要加上模板<>声明
编程实验
模板类的工程应用
Operator.h
#ifndef _OPERATOR_H_
#define _OPERATOR_H_
template < typename T >
class Operator
{
public:
T add(T a, T b); //函数声明
T minus(T a, T b);
T multiply(T a, T b);
T divide(T a, T b);
};
template < typename T > //模板<>声明
T Operator<T>::add(T a, T b)
{
return a + b;
}
template < typename T >
T Operator<T>::minus(T a, T b)
{
return a - b;
}
template < typename T >
T Operator<T>::multiply(T a, T b)
{
return a * b;
}
template < typename T >
T Operator<T>::divide(T a, T b)
{
return a / b;
}
#endif
58-2.cpp
#include <iostream>
#include <string>
#include "Operator.h"
using namespace std;
int main()
{
Operator<int> op1; //显示声明模板
cout << op1.add(1, 2) << endl; //3
cout << op1.multiply(4, 5) << endl; //20
cout << op1.minus(5, 6) << endl; //-1
cout << op1.divide(10, 5) << endl; //2
return 0;
}
操作:
1) g++ 58-2.cpp -o 58-2.out编译正确,打印结果:
3
20
-1
2
分析:
模板在使用时必须显示声明类型。
小结
1) 泛型编程的思想可以应用于类
2) 类模板以相同的方式处理不同类型的数据
3) 类模板非常适用于编写数据结构相关的代码
4) 类模板在使用时只能显示指定类型