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;
}