1、缺省模板参数
可以将数据结构类型传递进来,比如=vectop<T>(如果没传就是默认)
把vector当作类型参数来传递,从而使用它的接口然后适配出新的接口。实际上这个Stack称为适配器。有时候可能需要vector,但是又需要超出vector本身自带的功能,这时候就需要适配器,将vector当作参数传进去,嵌入到新写的模板中,这样就能适配原vector和新功能。
Stack.h
#include <stdexcept>
#include <deque>
using namespace std;template <typename T, typename CONT = deque<T> >
class Stack
{
public:explicit Stack();~Stack();void Push(const T& elem);void Pop();T& Top();const T& Top() const;bool Empty() const;private:CONT c_;
};template <typename T, typename CONT>
Stack<T, CONT>::Stack() : c_()
{}template <typename T, typename CONT>
Stack<T, CONT>::~Stack() {}template <typename T, typename CONT>
void Stack<T, CONT>::Push(const T& elem)
{c_.push_back(elem);
}template <typename T, typename CONT>
void Stack<T, CONT>::Pop()
{c_.pop_back();
}template <typename T, typename CONT>
T& Stack<T, CONT>::Top()
{return c_.back();
}template <typename T, typename CONT>
const T& Stack<T, CONT>::Top() const
{return c_.back();
}template <typename T, typename CONT>
bool Stack<T, CONT>::Empty() const {return c_.empty();
}
main.cpp
#include <iostream>
using namespace std;
#include "Stack.h"
#include <vector>int main() {Stack<int, vector<int> > s;s.Push(1);s.Push(2);s.Push(3);while (!s.Empty()){cout << s.Top() << endl;s.Pop();}return 0;
}// 输出
3
2
1
2、成员模板
上面的最后一行会报错,因为d已经定义成了double型,但是此时传入了int型。所以要把成员函数定义成模板。
注意这样子定义的话,x不能直接访问私有成员value,因为调用Assign的时候,参数的类型有可能和对象的类型不一样,不一样的时候,其实是两个类,类之间不能直接访问私有成员。同一种类型才能访问私有成员。
3、关键字typename的作用
如果没有typename,那么编译器就会解析成这样:这个T是一个类型,然后::域运算符,取到这个类中的静态数据成员SubType,然后*被解析成乘以,变成了SubType 乘以 ptr;
所以有typename则表示,后面的是一个类型,定义一个T::SubType类型的指针ptr
template <typename T>
class MyClass
{
private:typename T::SubType* ptr_;
};class Test
{
public:typedef int SubType; // 这边的话必须声明为public
};int main() {MyClass<Test> myclass;
}