C++基础——类模板


类模板

类模板stack的实现

有两个角度观察STL中的stack模板类

  • 模板类

通过将stack定义为模板类的形式实现stack类实体对不同类型数据(模板参数指定)的存储支持。

template<typename T>
class stack
{
...
private:
    std::deque<T> elems;
}
  • 适配器

以某种既有容器作为底部结构,将其接口改变,使之符合“先进后出”的特性,形成一个stackSTL deque是双向开口的数据结构,以deque作为底部结构并封闭其头端开口,便可实现一个stackSTL便以deque作为缺省情况下的stack的底部结构。(使用deque而不是vector来实现一个stack是有好处的,当删除元素时,deque会释放内存,当需要重新分配内存时,deque的元素不需要被移动)。

像这种狐假虎威,完全以底部容器完成全部工作,而具有修改某物接口,形成另一种风貌性质者,称为adapter(配接器)。STL的观点来看,stack往往不被归类为container,而被归类为container adapter,对底层容器的配接。

#include <deque>
#include <stdexpt>

template<typename T>
class stack
{
public:
    void push(const T&);
    void pop();
    const T& top() const;
    T& top();
    bool empty() const { return elems.empty();}
private:
    std::deque<T> elems;
}

template<typename T>
void stack<T>::push(const T& elem)
{
    elems.push_back(elem);      // 末尾进
}

template<typename T>
void stack<T>::pop()
{
    if (empty())
        throw std::out_of_range("stack<>::pop(): empty stack");
    elems.pop_back();           // 末尾出
}

template<typename T>
const T& stack<T>::top() const
{
    if (empty())
        throw std::out_of_range("stack<>::top(): empty stack");
    return elems.back();
}

template<typename T>
T& stack<T>::top()
{
    if (empty())
        throw std::out_of_range("stack<>::top(): empty stack");
    return elems.back();
}

拷贝构造函数和赋值运算符

  • 类名:Stack
  • 类的类型:Stack
template<typname T>
class Stack
{
public:
    Stack(const Stack<T>& rhs);
    Stack<T>& operator=(const Stack<T>& rhs);
}

类模板的特化

可以使用模板实参来特化类模板。为了特化一个类模板,你必须在起始处声明一个template<>(告诉编译器,这是一个特化版本),接下来声明用来特化的类模板的类型。如果你要特化一个类模板,你还要特化该类模板的所有成员函数。

template<>
class Stack<std::string>
{...}

进行类模板的特化时,每个成员函数都必须定义为普通函数,原来模板函数中的每个T也被相应的特化的类型所取代:

void Stack<std::string>::push(const std::string& elem)
{
    elems.push_back(elem);
}

在特化的版本中,我们也可将底层容器类型改变为vector,这说明,特化的实现可以和基本类模板(primary template)的实现完全不同。

局部特化

类模板可以被局部特化。在特定的环境下指定类模板的特定实现,并且要求某些模板参数仍然必须由用户来定义。

template<typename T1, typename T2>
class MyClass
{
    ...
}

可以做如下的局部特化:

// 局部特化:两个模板参数具有相同的类型 
template<typename T>
class MyClass<T, T>
{
    ...
}

// 局部特化:指定第二个模板参数为int
template<typename T>
class MyClass<T, int>
{
    ...
}

// 局部特化,两个模板参数都是指针类型
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*>

如果有多个局部特化同等程度地匹配某个声明,称这样的声明具有二义性。

MyClass<int, int> mii;      // 错误:同等程度地匹配MyClass<T, T>, MyClass<T, int>
MyClass<int*, int*> mpp;    // 错误:同等程度地匹配MyClass<T, T>, MyClass<T1*, T2*>

为了解决第二种二义性,可提供一种指向相同类型指针的特化:

template<typename T>
class MyClass<T*, T*>
{...}

缺省模板实参

template<typename T, typename CONT = std::deque<T> >
class Stack
{
public:
    void push(const T& elem);
private:
    CONT elems;
};

template<typename T, typename CONT>
void Stack<T, CONT>::push(const T& elem)
{
    elems.push_back(elem);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五道口纳什

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值