模板参数
默认类型参数
函数参数可以设定一个默认值,我们现在可以对类模板的类型参数设定一个默认类型。
指定泛型Stack的默认类型参数为 int
template<typename T = int>
class Stack{
...
};
当我们这样定义一个对象时:
Stack<> stack;
使用默认的方式,或者说隐式的方式,实例化了一个stack对象。
这样的好处是:指定默认类型之后,使用者就没必要去写了。
非类型参数
在模板前缀中使用非类型参数。
实例化模板时,非类型实参应该是对象。
如下:
template<typename T, int capacity>
class Stack {
...
private:
T elements[capacity];
int size;
};
Stack<char, 100> charStack;
如同std里面的array的初始化:std::array<int,100>;
除了基本数据类型外,非类型实参是对象的时候是这样的;
template<typename T, Color c>
class Label {
...
};
Color color(0,0,255);
Label<char,color> label;
注意,参数默认值必须是在最右边,当然我们也可以全部定义一个默认值,这样就不会有问题了。
注意模板成员函数的声明也需要进行修改。
就是这样:
//泛型化
template <typename T = char,int N = 100>
//编写StackOfIntegers类
class Stack {
private:
T elements[N];
int size{ 0 };
public:
bool empty();
T peek();
T push(T value);
T pop();
int getSize();
Stack();
};
template <typename T, int N>
Stack<T,N>::Stack() {
size = 0;
for (auto& i : elements) {
i = 0;
}
}
模板继承
关于模板继承的几个原则:
1、普通类可从类模板实例继承。一个模板实例化之后就是一个类了,类与类之间可以继承。
2、模板可从普通类继承
3、类模板可继承类模板
也就是说,一个类是不可以从一个模板继承的,其他的三种组合方式都是可以的。
何时何地使用模板
使用别人写好的模板库时
对不同类型的数据做类似处理 (算法、容器、遍历等)
OOP or GP
泛型编程在C++中广泛使用,经常可以取代面向对象编程。
几乎整个C++标准库都依赖于泛型编程。
在C++标准库较少使用继承和运行时多态。异常、字符串和IO流中使用了较多的继承。