亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

淺析C++中模板的那點事

2020-01-26 15:49:43
字體:
來源:轉載
供稿:網友

1.什么是模板

假設現在我們完成這樣的函數,給定兩個數x和y求式子x^2 + y^2 + x * y的值 .考慮到x和y可能是 int , float 或者double類型,那么我們就要完成三個函數:

int fun(int x,int y);
float fun(float x,float y);
double fun(double x,double y);

并且每個fun函數內部所要完成的操作也是極其的相似。如下:

復制代碼 代碼如下:

int fun(int x,int y)
{
    int tmp = x *x + y * y + x * y;
    return tmp;
}
float fun(float x,float y)
{
    float tmp = x *x + y * y + x * y;
    return tmp;
}
double fun(double x,double y)
{
    double tmp = x *x + y * y + x * y;
    return tmp;
}

可以看出,上面的三個函數體除了類型不一樣之外,其他的完全一樣,那么如果能夠只寫一個函數就能完成上面的三個函數的功能該多好呢?如果從這三個函數提煉出一個通用函數,而它又適用于這三種不同類型的數據,這樣會使代碼的重用率大大提高。實際上C++中的模板正好就是來解決這個問題的。模板可以實現類型的參數化(把類型定義為參數),從而實現了真正的代碼可重用性。C++中的模板可分為函數模板和類模板,而把函數模板的具體化稱為模板函數,把類模板的具體化成為模板類。下面讓我們分別看看什么是函數模板和類模板吧~~~

2.模板函數

實際上我們利用函數模板,只需要一個函數就可能完成上面的三個函數了,千言萬語不如看代碼:

復制代碼 代碼如下:

#include <iostream>

using namespace std;

template <typename T>
T fun(T x,T y)
{
    T tmp = x *x + y * y + x * y;
    return tmp;
}
int main()
{
    int x1 = 1,y1 = 4;
    float x2 = 1.1 , y2 = 2.2;
    double x3 = 2.0 , y3 = 3.1;
    cout<<fun(x1,y1)<<endl;
    cout<<fun(x2,y2)<<endl;
    cout<<fun(x3,y3)<<endl;
    return 0;
}


運行結果:

如此利用模板,我們很輕而易舉的達到了我們的目的,而這也大大的提高了代碼的可重用性,這也讓我們想起了STL中的那些算法了吧,這些算法使用多種的數據類型。實際上STL即使模板的重要應用了。

現在我們想,如果上面的代碼這樣調用fun(x1,y2)會怎么樣呢?點擊編譯會出現這樣的錯誤:

可以看到編譯編譯出現問題的是fun(x1,y2),說的意思就是沒有對應的函數,要么x1和y2都是int型,要么x1和y2都是float型。那么我為什么要說一下這樣一種情況呢?主要是為了引出模板也可以同時使用兩個:

復制代碼 代碼如下:

#include <iostream>

using namespace std;


template <typename T1 , typename T2>
T2 fun(T1 x,T2 y)
{
    T2 tmp = x *x + y * y + x * y;
    return tmp;
}
int main()
{
    int x1 = 1,y1 = 4;
    float x2 = 1.1 , y2 = 2.2;
    double x3 = 2.0 , y3 = 3.1;
    cout<<fun(x1,y1)<<endl;
    cout<<fun(x2,y2)<<endl;
    cout<<fun(x3,y3)<<endl;
    cout<<fun(x1,y2)<<endl;
    return 0;
}


運行結果:

當使用兩個模板時,為什么fun(x1,y1)也能正確運行呢?因為當進行這個調用時,T1 = int ,T2 = int。所以這種調用也是沒有問題的。

提到函數想到重載是很自然的吧,那么模板函數能不能重載呢?顯然是能的了,還是看代碼:

復制代碼 代碼如下:

#include <iostream>

using namespace std;


template <typename T1 , typename T2>
T2 fun(T1 x,T2 y)
{
    cout<<"調用了兩個個參數的 fun 函數 ^^ "<<endl;
    T2 tmp = x *x + y * y + x * y;
    return tmp;
}
template <typename T>
T fun(T x , T y , T z)
{
    cout<<"調用了三個參數的 fun 函數 ^^ "<<endl;
    T tmp = x * x + y * y + z * z + x * y * z;
    return tmp;
}
int main()
{
    int x1 = 1 , y1 = 4 , z1 = 5;
    float x2 = 1.1 , y2 = 2.2;
    double x3 = 2.0 , y3 = 3.1;
    cout<<fun(x1,y1)<<endl;
    cout<<fun(x2,y2)<<endl;
    cout<<fun(x3,y3)<<endl;
    cout<<fun(x1,y2)<<endl;
    cout<<fun(x1,y1,z1)<<endl;
    return 0;
}


運行結果:

從結果已經能看出來模版函數的重載是沒有任何問題的了。那么模板函數和非模板函數之間是否能夠重載呢??

復制代碼 代碼如下:

#include <iostream>

using namespace std;

template <typename T>
T fun(T x,T y)
{
    cout<<"調用了模板函數 ^^ "<<endl;
    T tmp = x * x + y * y + x * y;
    return tmp;
}
int fun(int x,int y)
{
    cout<<"調用了非模板函數 ^^ "<<endl;
    int tmp = x * x + y * y + x * y;
    return tmp;
}

int main()
{
    int x1 = 1 , y1 = 4;
    float x2 = 1.1 , y2 = 2.2;
    cout<<fun(x1,y1)<<endl;
    cout<<fun(x2,y2)<<endl;
    return 0;
}


運行結果:

看以看出模版函數和非模板函數也是可能重載的,那么重載函數的調用順序是怎么樣的呢?實際上是先查找非模板函數,要有嚴格匹配的非模板函數,就調用非模板函數,找不到適合的非模板函數在和模板函數進行匹配。

到這里,關于模板就說這些吧~~~~

3.模板類

要是理解了模版函數,模板類就相當的簡單了,只不過模版函數是對函數中的類型使用模板,而模板類是對類中的類型使用模板,這我就不多說了,下面的代碼是我以前利用模板寫的單鏈表,這個是模板的典型應用:(測試過)

復制代碼 代碼如下:

#include <stdio.h>
#include <iostream.h>

template <class T>
struct SLNode
{
    T data;
    SLNode<T> *next;
    SLNode(SLNode<T> *nextNode=NULL)
    {
        next = nextNode;
    }
    SLNode(const T &item,SLNode<T> *nextNode=NULL)
    {
        data = item;
        next = nextNode;
    }
};

template <class T>
class SLList
{
private:
    SLNode<T> *head;
    SLNode<T> *tail;
    SLNode<T> *currptr;
    int size;
public:
    SLList();
    SLList(const T &item);
    ~SLList();
    bool IsEmpty()const;
    int Length()const;
    bool Find(int k,T &item)const;
    int Search(const T &item)const;
    void InsertFromHead(const T &item);
    void InsertFromTail(const T &item);
    bool DeleteFromHead(T &item);
    bool DeleteFromTail(T &item);
    void Insert(int k,const T &item);
    void Delete(int k,T &item);
    void ShowListMember();
};
//構造函數
template <class T>
SLList<T>::SLList()
{
    head = tail = currptr = new SLNode<T>();
    size = 0;
}
//構造函數
template <class T>
SLList<T>::SLList(const T &item)
{
    tail = currptr = new SLNode<T>(item);
    head = new SLNode<T>(currptr);
    size = 1;
}
//析構函數
template <class T>
SLList<T>::~SLList()
{
     SLNode<T> *temp;
    while(!IsEmpty())
    {
        temp = head->next;
        head->next = temp->next;
        delete temp;

    }
}
//判斷鏈表是否為空
template <class T>
bool SLList<T>::IsEmpty()const
{
    return head->next == NULL;
}
//返回鏈表的長度
template <class T>
int SLList<T>::Length()const
{
     return size;
}
//查找第k個節點的閾值
template <class T>
bool SLList<T>::Find(int k,T &item)const
{
    if(k < 1)
    {
        cout<<"illegal position !"<<endl;
    }
    SLNode<T> *temp = head;
    int count = 0;
    while(temp != NULL && count < k)
    {
        temp = temp->next;
        count++;
    }
    if(temp == NULL)
    {
        cout<<"The list does not contain the K node !"<<endl;
        return false;
    }
    item = temp->data;
    return true;
}
//查找data閾值為item是表的第幾個元素
template <class T>
int SLList<T>::Search(const T &item)const
{
    SLNode<T> *temp = head->next;
    int count = 1;
    while(temp != NULL && temp->data != item)
    {
        temp = temp->next;
        count++;
    }
    if(temp == NULL)
    {
        cout<<"The node does not exist !"<<endl;
        return -1;
    }
    else
    {
        return count;
    }
}
//從表頭插入
template <class T>
void SLList<T>::InsertFromHead(const T &item)
{   
    if(IsEmpty())
    {
        head->next = new SLNode<T>(item,head->next);
        tail = head->next;
    }
    else
    {
        head->next = new SLNode<T>(item,head->next);
    }
    size++;
}
//從表尾插入
template <class T>
void SLList<T>::InsertFromTail(const T &item)
{
    tail->next = new SLNode<T>(item,NULL);
    tail = tail->next;
    size++;
}
//從表頭刪除
template <class T>
bool SLList<T>::DeleteFromHead(T &item)
{
    if(IsEmpty())
    {
        cout<<"This is a empty list !"<<endl;
        return false;
    }
    SLNode<T> *temp = head->next;
    head->next = temp->next;
    size--;
    item = temp->data;
    if(temp == tail)
    {
        tail = head;
    }
    delete temp;
    return true;
}
//從表尾刪除
template <class T>
bool SLList<T>::DeleteFromTail(T &item)
{
    if(IsEmpty())
    {
        cout<<"This is a empty list !"<<endl;
        return false;
    }
    SLNode<T> *temp = head;
    while(temp->next != tail)
    {
        temp = temp->next;
    }
    item = tail->data;
    tail = temp;
    tail->next=NULL;
    temp = temp->next;
    delete temp;
    size--;
    return true;
}
//在第k個節點后插入item值
template <class T>
void SLList<T>::Insert(int k,const T &item)
{
    if(k < 0 || k > size)
    {
        cout<<"Insert position Illegal !"<<endl;
        return;
    }
    if(k == 0)
    {
        InsertFromHead(item);
        return;
    }
    if(k == size)
    {
        InsertFromTail(item);
        return;
    }
    SLNode<T> *temp = head->next;
    int count = 1;
    while(count < k)
    {
        count++;
        temp = temp->next;
    }
    SLNode<T> *p = temp->next;
    temp->next = new SLNode<T>(item,p);
    size++;
}
//刪除第k個節點的值,保存在item中
template <class T>
void SLList<T>::Delete(int k,T &item)
{
    if(k <= 0 || k > size)
    {
        cout<<"Ileegal delete position !"<<endl;
        return;
    }
    if(k == 1)
    {
        DeleteFromHead(item);
        return;
    }
    if(k == size)
    {
        DeleteFromTail(item);
        return;
    }
    SLNode<T> *temp = head->next;
    int count = 1;
    while(count < k-1)
    {
        count++;
        temp = temp->next;
    }
    SLNode<T> *p = temp->next;
    temp->next = p->next;
    p->next = NULL;
    item = p->data;
    delete p;
    size--;
}
template <class T>
void SLList<T>::ShowListMember()
{
    cout<<"List Member : ";
    SLNode<T> *temp = head->next;
    while(temp != NULL)
    {
        cout<<temp->data<<" ";
        temp = temp->next;
    }
    cout<<endl;
}

/*
1.引入了InsertFronHead,InsertFromTail,DeleteFromHead和DeleteFromTail用來實現Insert和Delete函數,是一個比較好的方法。

2.SLNode(T &item,SLNode<T> *nextNode)這個構造函數設計的非常巧妙,便于其他成員函數的實現。

3.插入,刪除分為:表頭,表尾,中間插入(刪除)三種情況
*/

int main()
{
    int item;
    SLList<int> list(12);

    list.Insert(0,11);
    cout<<"list number:"<<list.Length()<<endl;
    list.ShowListMember();

    list.Insert(2,14);
    cout<<"list number:"<<list.Length()<<endl;
    list.ShowListMember();

    list.Insert(2,13);
    cout<<"list number:"<<list.Length()<<endl;
    list.ShowListMember();

    list.Delete(2,item);
    cout<<"item = "<<item<<endl;
    cout<<"list number:"<<list.Length()<<endl;
    list.ShowListMember();

    list.Delete(1,item);
    cout<<"item = "<<item<<endl;
    cout<<"list number:"<<list.Length()<<endl;
    list.ShowListMember();

    list.Delete(2,item);
    cout<<"item = "<<item<<endl;
    cout<<"list number:"<<list.Length()<<endl;
    list.ShowListMember();
    return 0;
}


利用模板的好處是,SLList中的數據可以是任意的數據類型,這也就是泛型編程的概念了吧~~~~

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91精品国产91久久久久久| www.美女亚洲精品| 亚洲欧美激情另类校园| 精品福利一区二区| 国产日韩欧美在线播放| 亚洲天堂成人在线视频| 亚洲第一视频在线观看| 亚洲国产精品高清久久久| 欧美一级视频一区二区| 亚洲电影av在线| 在线观看欧美日韩| 欧美性猛交xxxx富婆弯腰| 久久99久久久久久久噜噜| 欧美日韩精品在线观看| 日韩美女免费视频| 欧美性猛交xxxx偷拍洗澡| 91国偷自产一区二区三区的观看方式| 久久激情五月丁香伊人| 成人黄色影片在线| 色哟哟亚洲精品一区二区| 欧美极品少妇与黑人| 国产精品久久999| 午夜精品一区二区三区在线| 国语自产在线不卡| 最好看的2019的中文字幕视频| 国产精品成人在线| 狠狠色狠色综合曰曰| 亚洲精品网址在线观看| 国产日韩欧美在线| 亚洲国产精品女人久久久| 69av视频在线播放| xxxxx91麻豆| 福利精品视频在线| 欧美最近摘花xxxx摘花| 国内免费精品永久在线视频| 欧美国产亚洲精品久久久8v| 久久综合亚洲社区| 国产suv精品一区二区| 日韩在线视频免费观看高清中文| 久久色精品视频| 91人人爽人人爽人人精88v| 欧美wwwwww| 欧美又大粗又爽又黄大片视频| 麻豆精品精华液| 国产97在线|日韩| 欧美激情啊啊啊| 国产精品影片在线观看| 精品香蕉在线观看视频一| 成人深夜直播免费观看| 欧美福利视频在线| 亚洲成色www8888| 在线国产精品视频| 欧美日韩国产中文精品字幕自在自线| 久久97精品久久久久久久不卡| 欲色天天网综合久久| 日韩欧美在线免费| 麻豆国产精品va在线观看不卡| 欧美激情欧美狂野欧美精品| 另类专区欧美制服同性| 国产精品高清免费在线观看| 欧美国产日本在线| 亚洲电影免费观看高清完整版在线观看| 欧美在线视频导航| 欧美激情视频网站| 深夜精品寂寞黄网站在线观看| 国产午夜精品麻豆| 日韩免费中文字幕| 日本久久久久久久| 疯狂做受xxxx高潮欧美日本| 精品综合久久久久久97| 欧美一级黑人aaaaaaa做受| 国产精品久久国产精品99gif| 色播久久人人爽人人爽人人片视av| 最近日韩中文字幕中文| 久久综合色影院| 国产欧美日韩精品丝袜高跟鞋| 最近日韩中文字幕中文| 国产精品久久久久久久久男| 欧美成人中文字幕在线| 日韩电视剧免费观看网站| 亚洲性av网站| 国产精品国模在线| 色综合视频网站| 91九色国产社区在线观看| 日韩免费观看在线观看| 久久久精品免费| 一区二区三区亚洲| 538国产精品一区二区免费视频| 成人性教育视频在线观看| 亚洲欧美在线一区二区| 欧美中文在线观看| 久久99精品久久久久久琪琪| 色天天综合狠狠色| 久久人人爽人人爽人人片av高清| 久久久综合免费视频| 色无极影院亚洲| 国产一区二区视频在线观看| 精品调教chinesegay| 欧洲精品毛片网站| 久久久久国色av免费观看性色| 国产精品欧美一区二区三区奶水| 亚洲一区二区三| 91在线色戒在线| 亚洲天堂av电影| 国产成人精品电影久久久| 69av视频在线播放| 亚洲精品电影久久久| 欧美成人精品激情在线观看| 97在线视频免费播放| 欧美高清自拍一区| 日韩免费黄色av| 亚洲天堂影视av| 中文字幕在线观看日韩| 亚洲人成电影网站色xx| 国产色婷婷国产综合在线理论片a| 亚洲性线免费观看视频成熟| 国产精品久久久久久久久| 国产精品一二三在线| 日韩精品福利在线| 97成人精品区在线播放| 日韩av免费一区| 中文字幕日韩av综合精品| 亚洲老板91色精品久久| 日韩在线观看高清| 51午夜精品视频| 亚洲一区亚洲二区亚洲三区| 日韩电影中文 亚洲精品乱码| 久久亚洲精品中文字幕冲田杏梨| 国产精品自拍视频| 一区二区在线免费视频| 国产精品色视频| 2024亚洲男人天堂| 欧美亚洲第一区| 97精品一区二区视频在线观看| 2019中文字幕在线免费观看| 日韩在线观看你懂的| 日韩欧美精品在线观看| 久精品免费视频| 91香蕉国产在线观看| 精品自拍视频在线观看| 欧美在线www| 成人www视频在线观看| 欧美国产日韩中文字幕在线| 亚洲黄一区二区| 亚洲欧美日韩国产成人| 欧美成aaa人片在线观看蜜臀| 亚洲乱码国产乱码精品精| 国产精品视频yy9099| 2023亚洲男人天堂| 日本高清不卡的在线| 欧美精品18videos性欧美| 欧美高跟鞋交xxxxxhd| 欧美性猛交xxxx免费看久久久| 中文字幕在线看视频国产欧美| 97涩涩爰在线观看亚洲| 亚洲系列中文字幕| 久久久999精品免费| 亚洲人成电影网站色www| 日韩欧美中文字幕在线播放| 午夜欧美不卡精品aaaaa| 国产ts人妖一区二区三区| 亚洲欧美日韩一区在线| 性金发美女69hd大尺寸| 国产精品女人网站|