模板(三)

缺省模板参数


  • template < typename T, typename CONT = deque< T > >

#ifndef _STACK_H_
#define _STACK_H_

#include <exception>
#include <deque>
using namespace std;

template <typename T, typename CONT = deque<T> >
class Stack
{
public:
    Stack();                //防止隐式转换
    ~Stack();
    void Push(const T& elem);
    void Pop();
    T& Top();
    const T& Top() const;
    bool Empty() const;
private:
    CONT c_;
    int top_;
};

template <typename T, typename CONT = deque<T> >
Stack<T, CONT>::Stack() : c_()
{
}

template <typename T, typename CONT = deque<T> >
Stack<T, CONT>::~Stack()
{
}

template <typename T, typename CONT = deque<T> >
void Stack<T, CONT>::Push(const T& elem)
{
    c_.push_back(elem);
}

template <typename T, typename CONT = deque<T> >
void Stack<T, CONT>::Pop()
{
    if (c_.empty())
        throw out_of_range("Stack::Pop() Stack empty");
    c_.pop_back();
}

template <typename T, typename CONT = deque<T> >
T& Stack<T, CONT>::Top()
{
    if (c_.empty())
        throw out_of_range("Stack::Pop() Stack empty");
    return c_.back();

}

template <typename T, typename CONT = deque<T> >
const T& Stack<T, CONT>::Top() const
{
    if (c_.empty())
        throw out_of_range("Stack::Pop() Stack empty");
    return c_.back();

}

template <typename T, typename CONT = deque<T> >
bool Stack<T, CONT>::Empty() const
{
    return c_.empty();
}

#endif // _STACK_H_
#include "Stack.h"
#include <iostream>
#include <vector>
using namespace std;
int main(void)
{
    //Stack<int> s;             //第一种使用方法
    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;
}

成员模板

  • 为什么要有成员模板
template <typename T>
class Myclass
{
public:
    T value;
private:
    void Assign(const Myclass<T>& x)
    {
        value = x.value;
    }
};

//main函数中有如下语句

Myclass<double> d;
Myclass<int> i;

d.Assign(d);      //OK
d.Assign(i);      //Error

//类型不一样,无法传递
//这是我们就需要让成员函数也是模板
#include<iostream>
using namespace std;
template <typename T>
class Myclass
{
public: 
    Myclass()                   //默认构造函数
    {
    }

    template <typename X>       //模板构造函数
    Myclass(const Myclass<X>& x) : value(x.GetValue())
    {
    }

    template <typename X>       //模板函数
    void Assign(const Myclass<X>& x)
    {
        value = x.GetValue();   //当X和T不是同一种类型的时候,无法访问私有成员,必须提供接口函数
    }

    T GetValue() const
    {
        return value;
    }

private:
    T value;
};

//main函数中有如下语句
int main(void)
{
    Myclass<double> d;
    Myclass<int> i;

    d.Assign(d);                //OK
    d.Assign(i);                //OK
    Myclass<double> d1(i);      //必须要有模板构造函数

    return 0;
}

typename关键字

#include<iostream>
using namespace std;

template <typename T>
class Myclass
{
private:
    typename T::SubType* ptr_;  //如果此处没有typename,此处会将SubType解析为“T类型里的一个静态数据成员乘以ptr_"
};
class Test
{
public:
    typedef int SubType;
};
int main(void)
{
    Myclass<Test> mc;
    return 0;
}

派生类和模板区别


  • 为了运行的效率,类模板是相互独立的,即独立设计,没有使用继承的思想。对类模板的扩展是采用适配器(adapter)来完成的。通用性是模板库的设计出发点之一,这是由泛型算法和函数对象等手段达到的。

  • 派生的目标之一也是代码的复用和程序的通用性,最典型的就是MFC,派生类的优点是可以由简到烦,逐步深入,程序编制过程中可以充分利用前面的工作,一步步完成一个复杂的任务。

  • 模板追求的是运行效率,而派生类追求的是编程的效率。


面向对象与泛型编程


  • 面向对象与泛型都依赖于某个形式的多态

  • 面向对象

    • 动态多态 ——虚函数
    • 静态多态 ——模板
  • 面向对象中的多态在运行时应用存在继承关系。我们编写使用 这些类的代码,忽略使用基类与派生类之间的类型差异。只要使用基类指针或者引用,基类类型对象、派生类类型对象就可以共享相同的代码。

  • 在泛型编程中,我们所编写的类和函数能够多态的用于编译时不相关的类型。一个类或一个函数可以用来操作多种类型的对象。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值