C++ 模板

模板

        模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。模板是创建泛型类或函数的蓝图或公式。

函数模板

模板函数定义的一般形式如下所示:

//定义
template<class Type>
int compare(const Type& v1, const Type& v2)
{
   if(v1<v2) return -1;
   if(v1>v2) return 1;
   return 0;
}

//调用
const char* cp1 = "world", *cp2="hi";
 int i1=1,i2=2;
 compare(i1,i2);
 compare(cp1,cp2);

一般模板函数与特化模板函数

以compare函数举例

//一般模板函数
template<class Type>
int compare(const Type& v1, const Type& v2)
{
   if(v1<v2) return -1;
   if(v1>v2) return 1;
   return 0;
}

//特化模板函数
 template<>
 int compare<const char*>(const char * const &v1, const char * const &v2)
 {
     return strcmp(v1,v2);
 }

特化函数与模板函数的区别:

(1)、模板函数的T参数只能传入类类型的参数;特化函数的参数只能传入对应的参数类型,基本类型或类类型。

(2)、模板函数在link时检查类型,编译时只是当成了注释;特化函数及参数在编译时检查是否匹配或有错。

(3)、特化函数与模板函数重名时,特化函数需要加特殊处理。一种方式是加inline修饰,不在编译时生成对应的符号表。

类模板

        

template<class Type> class Queue;
template<class Type> class QueueItem{
    QueueItem(const Type &t):item(t), next(0){}
    Type item;
    QueueItem * next;
    friend class Queue<Type>;
    friend ostream& operator<<(ostream& os, const Queue<Type> &q);
};

成员模板函数

声明了类模板后,就可以将类型参数用于类的成员函数和成员变量,即原来使用 int、float、char 等内置类型的地方都可以用类型参数来代替。

#include <iostream>
using namespace std;


class Printer
{
public:
    template<typename T>//类的成员函数是模板
    void print(const T& t)
    {
        cout << t << endl;
    }

    template<typename T>
    void print(int a, const T& t)
    {
        cout << a << t << endl;
    }
};

int main()
{
    Printer p;
    p.print<const char*>("abc");                //类成员函数是模板的调用方式
    p.print("abc");                            //编译器推断参数模板类型
    p.print(2, "abc");                        //类模板成员函数重载
    getchar();
    return 0;
}

模板特化

        模板函数特化

        使用模板时会遇到一些特殊的类型需要特殊处理,不能直接使用当前的模板函数,所以此时我们就需要对该类型特化出一个模板函数(就是写出一个模板函数专门给该类型使用)

template<>
void Queue<const char*>::push(const char * const &val){
    char* new_item = new char[strlen(val)+1];
    strncpy(new_item,val,strlen(val)+1);
    QueueItem<const char*> * pt = new QueueItem<const char*>(new_item);
    if(empty()){
        head=tail=pt;
    }else{
        tail->next = pt;
        tail = pt;
    }
}
template<>
void Queue<const char*>::pop(){
    QueueItem<const char*> * p = head;
    delete head->item;
    head = head->next;
    delete p;
}

        模板成员函数特化

        当函数模板需要对某些类型进行特化处理,称为函数模板的特化。

template<>
void Queue<const char*>::push(const char * const &val){
    char* new_item = new char[strlen(val)+1];
    strncpy(new_item,val,strlen(val)+1);
    QueueItem<const char*> * pt = new QueueItem<const char*>(new_item);
    if(empty()){
        head=tail=pt;
    }else{
        tail->next = pt;
        tail = pt;
    }
}
template<>
void Queue<const char*>::pop(){
    QueueItem<const char*> * p = head;
    delete head->item;
    head = head->next;
    delete p;
}

        模板类特化

        类模板的特化:与函数模板类似,当类模板内需要对某些类型进行特别处理时,使用类模板的特化。

        在模板类里,所有的类型都是模板,当我们将所有的模板类型T都明确化,并且写了一个类名与主模板类名相同的类,那么这个类就叫做全特化类。偏特化就是介于二者之间的模板。

//模板类
template<typename T, class N> class Test_Class
{
public:
    static bool comp(T num1, N num2)
    {
        return (num1<num2)?true:false;
    }
};
 
 
//偏特化,模板类
template<class N> class Test_Class<int, N>
{
public:
    static bool comp(int num1, N num2)
    {
        return (num1<num2)?true:false;
    }
};

//全特化
template<>
class Queue<const char*>{
public:
    void Push(const char* str){real_queue.push(str);}
     void Pop(){real_queue.pop();}
     bool isEmpty()  {return real_queue.empty();}
     string front() const {return real_queue.front();}
     friend ostream & operator<<(ostream& os, Queue<const char*> &que){
         os<<que.real_queue;
     }
  //    const string &front() const{return real_queue.front();}

 private:
     Queue<string> real_queue;

 };

模板类(AutoPtr)

AutoPtr定义了类似指针的对象,将 new 获得的地址赋给该对象。当AutoPtr对象过期时,析构函数将使用 delete 来释放内存。如果将 new 返回的地址赋值给 AutoPtr对象,无须记住还需要释放这些内存。在 AutoPtr 对象过期时,内存将自动被释放。

构造函数

template<class T>
AutoPtr<T>::AutoPtr(T* pData)
{
    m_pData = pData;
    m_nUser = new int(1);
}


析构函数

template<class T>
AutoPtr<T>::~AutoPtr()
{
    decrUser();
}
 
template<class T>
void AutoPtr<T>::decrUser()
{
    --(*m_nUser);
    if((*m_nUser)==0){
        delete m_pData;
        m_pData = 0;
        delete m_nUser;
        m_nUser = 0;
    }
}


拷贝构造函数

AutoPtr<T>& AutoPtr<T>::operator=(const AutoPtr<T>& h)
{
    decrUser();
    m_pData = h.m_pData;
    m_nUser = h.m_nUser;
    (*m_nUser)++;
}


等号、->、*等运算符重载

public:
    T* operator->(){
        return m_pData;
    }
    T& operator*(){
        return *m_pData;
    }
    const T& operator *() const{
        return *m_pData;
    }
    const T* operator ->() const{
        return m_pData;
    }
AutoPtr<T>& AutoPtr<T>::operator=(const AutoPtr<T>& h)
{
    if(this==&h) return *this;
    decrUser();
    m_pData = h.m_pData;
    m_nUser = h.m_nUser;
    (*m_nUser)++;
    return *this;
}


主函数调用AutoPtr

int *a = new int(3);
    int *b = new int(7);
    AutoPtr<int> p(b);//建一个智能指针和b指向同个地方
    AutoPtr<int> t(p);//拷贝构造函数的使用
    AutoPtr<int> f(a);
    cout<<"p:"<<*p<<endl;
    cout<<"t:"<<*t<<endl;
    p=f;
    cout<<"p:"<<*p<<endl;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值