类模版 具体化 特化 部分特化 友元

本文详细介绍了C++中的类模板特化,包括全特化、部分特化以及具体化。强调了特化本质上是自定义实例,而部分特化仍为模板。此外,还提到了友元模板和声明式实例化类模板的重要概念。
摘要由CSDN通过智能技术生成

函数模版 特化

提前说明一下:

写类模版时把 <类型参数 >与 类名 看成一个整体 , 比较好理解;

比如 stack<int> 是一个类, stack<double> 是另一个类.

那么stack 呢?? 是一个用于生成类的模版,

即类模版是一个类的蓝图, 涉及到具体的类(stack<int>)则由编译器给我们生成;

如果看这些东西比较吃力, 建议先使用一下标准库的:vector, queue,stack 再学习模版

<这句话可以在看完模版后再回过头来看看>:

                            提前先说一下,全特化本质上就是一个实例,而部分特化还是一个模版;

每个类模版实例化的类都是一个独立的类:意思是可以随意添加任意成员变量与函数

首先1个常规的通用模版类:(具体化或特化 在下面介绍)

Stack.h

/*
 Stack.h

 类模版基本概念:
    如果把类看成对象的蓝图 , 则类模版可看作类的蓝图;

    template <typename T> 告诉编译器,你就按这个方式来生成这个类;

    到时如果有Stack<int> si; 编译器就会给生成 Stack<int> 这个类 (类模版在使用时才会生成代码,所以常常把模版的声明与定义放在一起)

    *把Stack<int> 看成一个整体,即Stack<int>是1个类, Stack是Stack<int>的模版;
     如有Stack<double> 又会生成1个类,这些代码生成工作是编译器给咱作的.

下面的例子中,把成员函数都放到类外定义了, 如在类内定义则不需要加Stack::<T>, 直接使用Stack,就像常规类定义;


编写下面代码时,新手需时时注意一点,模版不是类,模版的目的是让编译器生成类. 所以
下面代码把 Stack<T> 看成是一个类,而不是Stack . 如果看T比较麻烦,可以想像Stack<int> ;

*/


/*
这是一个正常的类:
class Stack{};

模版类需要加一个模版头去声明一下: template <typename T> 

(typename 表示类型名称是 T,T 表示一个类型,你就当成一个占位符就行了,那么 T 到底是什么类型呢? 由外部传入)
*/

//模版头,意思是下面这个类是一个模版.到时编译器将生成一个 Stack<XX> 类,例如Stack<int>;
template <typename T> 
class Stack
{
private:
    enum {MAX=10};
    T * items;
    int stackSize;
    int top;
public:
    //先介绍所有的成员函数在类外部定义的方式,类内定义与正常的类相同
    explicit Stack(int ss = MAX);
    Stack(const Stack &s);
   ~Stack();
    Stack& operator= (const Stack &s);
    bool isEmpty();
    bool isFull();
    bool push(const T& t);
    bool pop(T& t);
    void show() const;
};
template <typename T> //这里也必须写,暗示这是一个模版,不是一个类.除非定义在类内部.
Stack<T>::Stack(int ss) : top(0),stackSize(ss),items(0)    //注意:Stack<T>:: 而不是Stack
{
    items = new T[stackSize];
}
template <typename T> //注意所有的成员函数在类外部定义的时候都要额外添加模版头
Stack<T>::Stack(const Stack &s)
{
    stackSize = s.stackSize;
    top = s.top;
    items = new T[stackSize];
    for(int i = 0; i < top ; ++i)
        items[i] = s.items[i];
}
template <typename T>
Stack<T>::~Stack()
{
    if(items)
        delete[] items;
}
template <typename T>
Stack<T>& Stack<T>::operator=(const Stack<T> & s) //函数参数Stack<T>& ,而不是Stack&.因为Stack是一个模版
{
    if(this == &s)
        return *this;
    if(items)
        delete[] items;
    stackSize = s.stackSize;
    top = s.top;
    items = new T[stackSize];
    for(int i =0 ; i < top ; ++i)
        items[i] = s.items[i];
    return *this;
}

template <typename T>
bool Stack<T>::isEmpty()
{
    return top == 0;
}
template <typename T>
bool Stack<T>::isFull()
{
    return top == MAX;
}
template <typename T>
bool Stack<T>::push(const T &t)
{
    if(top < MAX)
    {
        items[top++] = t;
        return true;
    }
    return false;
}
template <typename T>
bool Stack<T>::pop(T &t)
{
    if(top > 0){
        t = items[--top];
        return true;
    }
    return false;
}
template <typename T>
void Stack<T>::show() const
{
    for(int i = 0; i < top ; ++i)
        std::cout << items[i] << std::endl;
}
以上需要注意的是:
每个成员函数的定义前都是 Stack<T>:: , 而不是Stack ; 同时每个成员函数上方都加了模版头 template<typename T>; (把template <typename T> 当成是1个参数列表)

原因是当加上了模版头template<typename T> 后, Stack已经是1个模版而不是类.
真正的类是编译给我们生成的, 何时生成呢?

比如 当使用了 Stack<string> 时 , 即生成了1个 Stack<string> 类;

如果函数在类内定义就简单很多了, 不需要再加Stack<T>:: 前缀, 也不需要在每个函数上放添加template <typename T>

此时:
Stack<int> si; 将生成一个类 class Stack<int>;
Stack<double> sd; 又生成一个类 class Stack<double>;

总之把<>内的类型参数列表与模版名Stack 看成一个整体会比较好理解模版生成的类;
再次强调 Stack 不是类,而是模版;

//main.cpp
//其他的方法就不测了.主要说明类模版

/*
    编译器将实例化一个类; 
    
    注意Stack<int> 这种方式
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值