一:类模板的定义
由于类模板包含类型参数,因此又称为参数化的类。如果说类是对象的抽象,对象是类的实例,则类模板是类的抽象,类是类模板的实例。利用类模板可以建立含各种数据类型的类 eg:vector<>、stack<>。
补充:类模板和模板类的区别
类模板(class template)说明的是该类的一个模板,它代表的是整个类家族的参数描述。
模板类(templa class)是从类模板中产生的类,即由模板名称与紧追其后的尖括号内部的所有实参的组合。
类模板的定义实例:
#include <vector>
#include <stdexcept>
template <typename T>
class Stack
{
public:
void push (T const& );
void pop();
T top() const;
bool empty() const
{
return elems.empty();
}
protected:
private:
std::vector<T> elems;
};
template <typename T>
void Stack<T>::push (T const& elem)
{
elems.push_back(elem);
}
template <typename T>
void Stack<T>::pop()
{
if (elems.empty())
{
throw std::out_of_range("Stack<>::pop() :empty stack");
}
elems.pop_back();
}
template <typename T>
T Stack<T>::top() const
{
if (elems.empty())
{
throw std::out_of_range("Stack<>::pop() :empty stack");
}
return elems.back();
}
说明:这个类的类型(即类模板的类型)是:Stack<T>,其中T是模板参数,因此在声明中需要声明该类的类型时,必须使用Stack<T>。eg:为了定义类模板的成员函数,你必须指定该成员函数是一个函数模板,而且还需要用这个类模板的完美类型限定符(上例是stack<T>).
二:类模板的使用
#pragma warning (disable :4786)
#include <iostream>
#include <string>
#include <cstdlib>
#include "stack.h"
using namespace std;
int main()
{
try{
Stack<int> intstack;
Stack<string> stringstack;
intstack.push(7);
cout<<intstack.top()<<endl;
stringstack.push("hello");
cout<<stringstack.top()<<endl;
stringstack.pop();
stringstack.pop();
}catch (std::exception const& ex) {
std::cerr<<"Exception: "<<ex.what()<<endl;
return EXIT_FAILURE;
}
return 0;
}
三:类模板的特化
在进行类模板的特化时,每个成员函数都必须重新定义为普通函数,原来模板函数中的每个T也相应地被进行特定的类型取代
四:局部特化
类模板可以被局部特化,你可以在特定的环境下指定类模板的特定实现,并且要求某些模板参数仍然必须有用户来定义。
eg:对于这样的类模板:
template <typename T1,typename T2>
class MyClass
{ ......... };
其有下列几种局部特化:
(1)
template <typename T>
class MyClass <T,T>
{ ......... };
(2)
template <typename T>
class MyClass <T,int>
{ ......... };
(3)
template <typename T1,typename T2>
class MyClass <T1*,T2*>
{ ......... };
这就以使用他们Myclass<int,float>mif //使用Myclass<T1,T2>
Myclass<float,float>mff //使用Myclass<T,T>
Myclass<float,int> mfi //使用Myclass<t,int>
Myclass<int *,float *>mp //实用Myclass<T1*,T2*>
但是使用时防止产生二义性:eg:MyClass<int,int>m //MyClass<T,T>和MyClass<T,int>都可以匹配
四:缺省模板实参
#include <vector>
#include <stdexcept>
template <typename T,typename cont=std::vector<T> >
class Stack
{
public:
void push (T const& );
void pop();
T top() const;
bool empty() const
{
return elems.empty();
}
protected:
private:
cont elems;
};
template <typename T,typename cont=std::vector<T> >
void Stack<T>::push (T const& elem)
{
elems.push_back(elem);
}
template <typename T,typename cont=std::vector<T> >
void Stack<T>::pop()
{
if (elems.empty())
{
throw std::out_of_range("Stack<>::pop() :empty stack");
}
elems.pop_back();
}
template <typename T,typename cont=std::vector<T> >
T Stack<T>::top() const
{
if (elems.empty())
{
throw std::out_of_range("Stack<>::pop() :empty stack");
}
return elems.back();
}
使用时可以是:
Stack<int> intStack;
Stack<double,std::queue<double> > doublesStack; //声明了一个”元素类型为double,并且使用std:queue<>在内部管理元素“的栈;
小结:
类模板是具有如下性质的类:
在类的实现中,可以有一个或多个类型还没有被指定。
为了使用类模板,你可以传入某个具体类型作为模板参数,然后编译器将会基于该类型来实例化类模板。
对于类模板而言,只有那些被调用的成员函数才会被实例化
可以用某种特定类型特定化类模板
可以用某种特定类型局部特化类模板
可以为类模板的参数定义缺省值,这些值还可以引用之前的模板参数
更多推荐
模板之类模板
发布评论