全文为个人理解总结用
《C++ primer plus》14章 类模板概念
有点理解不来。梳理一遍。
- 核心要义:模板,是为了满足重用代码的需求。
(比如一套代码,多种数据类型皆可使用。) - 百度百科:
泛型即是指具有在多种数据类型上皆可操作的含义,与模板有些相似。
语法
类模板的声明和定义
- 一个普通的Stack类(栈类)
Stack.h
typedef unsigned long Item;
class Stack
{
private:
enum {MAX = 10};
Item item[max];
int top;
public:
Stack();
bool isempty() const;
bool isfull() const;
bool push(const Item & item};
bool pop(Item & item);
}
- 声明为类模板的Stack类
Stack.h
template <typename Type>//早期编译器需要这种写法template <class Type >
class Stack
{
private:
enum {MAX = 10};
Type item[max]; //(声明的唯一区别在 item 的数据类型上)
int top;
public:
Stack();
bool isempty() const;
bool isfull() const;
bool push(const Item & item};
bool pop(Item & item);
}
Stack.cpp
template <typename Type>
Stack<Type>::Stack()
{
top = 0;
}
template <typename Type>
bool Stack<Type>::isempty()
{
return top == 0;
}
template <typename Type>
bool Stack<Type>::isfull()
{
return top == MAX;
}
template <typename Type>
bool Stack<Type>::push(const Type & item)
{
if(top < MAX)
{
items[top++] = item;
return true;
}
else
{
return false;
}
}
template <typename Type>
bool Stack<Type>::pop(Type & item)
{
if(top > 0)
{
item = items[--top];
return true;
}
else
{
return false;
}
}
使用上的区别
-
一个普通的Stack使用(数据类型为固定 Item 类型):
Stack val_nomal; -
一个类模板Stack使用(增加类型指定,同一套代码,可以多个类型使用):
Stack val1;
Stack val2; -
类模板的声明和定义需要一一对应,因此 每个方法的定义,都附上了Type 类型。
-
Type 的值为 数据类型(泛型名), 因此也叫类型参数。
数组模板 和 非类型参数
- 模拟array
ArrayTP.h
template <typename T, int n>
class ArrayTP //array template
{
private:
T ar[n];
public:
ArrayTP() {};
explicit ArrayTP(const T & v);
virtual T & operator[](int i);
virtual T operator[](int i)const;
}
ArrayTP.cpp
template <typename T, int n>
ArrayTP<T,n>::ArrayTP(const T &v)
{
for(int i = 0; i < n; i++)
{
ar[i] = v;
}
}
template <typename T, int n>
T & ArrayTP<T,n>::operator[](int i)
{
if(i <0 || i >= n)
{
std::cerr << "Error in array limits: " << i << "is out of range\n";
std::exit[EXIT_FALLURE];
}
return ar[i];
}
template <typename T, int n>
T ArrayTP<T,n>::operator[](int i) const
{
if(i <0 || i >= n)
{
std::cerr << "Error in array limits: " << i << "is out of range\n";
std::exit[EXIT_FALLURE];
}
return ar[i];
}
- 数组模板,ArrayTP为数组功能,第二参数 int n 为数组长度。
- 非类型参数,第二参数固定为int, 所以只能输入数值,而不能输入数据类型,称为非类型参数。
- 使用上:
ArrayTP<double, 10> array_val; - 缺陷:模板,会被具体化, 因此,不同参数就会生成不同的类。
比如 ArrayTP<double 12>和ArrayTP<double 10>,编译器会生成两个类。
并且,n 的值不能够被改变,也不能使用其地址。
模板的多功能性
1递归使用模板
- ArrayTP<ArrayTP<int ,5> , 10 > twodee;
那上述相当于:int twodee[10][5]
2使用多个类型参数
template <typename T1, typename T2>
class Topo{ … }
3默认类型模板参数
template <typename T1, typename T2 = int>
class Topo{ … }
- 如果省略T2的值,编译器将使用int
模板的具体化
1隐式实例化
- 上面那些直接用的就是隐式实例化
2显示实例化
- template class ArrayTP<string, 100>;
上述语句,可以在声明和定义之后,进行显示的实例化。
3显示具体化(对模板的一个指定的数据类型,做指定的处理)
- 显示具体化是特定类型的定义,有时候,可能需要在为特殊类型实例化时,对模进行修改,使其行为不同。
基本模板定义:
template
class SortedArray
{
…//
};
具体化模板定义格式:
template <> class Classname{ … }
template <> class SortedArray<const char *>
4部分具体化
- template >typename T1> class Class_name<T1, int >
成员模板(模板可用作结构、类或模板类的成员)
将模板用作参数
模板类和友元
- 1 模板类的非模板友元函数
- 2 模板类的约束模板友元函数
- 3 模板类的非约束模板友元函数