C++ 模板

Dec 13, 2016 pm 02:31 PM
template

函式模板

在c++入門中,很多人會接觸swap(int&, int&)這樣的函數類似程式碼如下:

void swap(int&a , int& b) {
    int temp = a;
    a =  b;
    b = temp;
}
登入後複製

但是如果是要支援long,string,自訂class的swap函數,程式碼和上述程式碼差不多,只是型別不同,這個時候就是我們定義swap的函式範本,就可以重複使用不同類型的swap函數程式碼,函數模板的宣告形式如下:

template <class identifier> function_declaration;
template <typename identifier> function_declaration;
登入後複製

swap函數模板的宣告和定義碼如下:

//method.h
template<typename T> void swap(T& t1, T& t2);

#include "method.cpp"
登入後複製
//method.cpp

template<typename  T> void swap(T& t1, T& t2) {
    T tmpT;
    tmpT = t1;
    t1 = t2;
    t2 = tmpT;
}
登入後複製

上述是模板的宣告和定義了,那模板如何實例化呢,模板的實例化是編譯器做的事情,與程式設計師無關,那麼上述模板如何使用呢,程式碼如下:

//main.cpp
#include <stdio.h>
#include "method.h"
int main() {
    //模板方法 
    int num1 = 1, num2 = 2;
    swap<int>(num1, num2);
    printf("num1:%d, num2:%d\n", num1, num2);  
    return 0;
}
登入後複製

這裡使用swap函數,必須包含swap的定義,否則編譯會出錯,這個和一般的函數使用不一樣。所以必須在method.h檔的最後一行加入#include "method.cpp"。

類模板

考慮我們寫一個簡單的棧的類,這個棧可以支持int類型,long類型,string類型等等,不利用類模板,我們就要寫三個以上的stack類,其中代碼基本一樣,透過類別模板,我們可以定義一個簡單的棧模板,再根據需要實例化為int棧,long棧,string棧。

//statck.h
template <class T> class Stack {
    public:
        Stack();
        ~Stack();
        void push(T t);
        T pop();
        bool isEmpty();
    private:
        T *m_pT;        
        int m_maxSize;
        int m_size;
};

#include "stack.cpp"
登入後複製
//stack.cpp
template <class  T>  Stack<T>::Stack(){
   m_maxSize = 100;      
   m_size = 0;
   m_pT = new T[m_maxSize];
}
template <class T>  Stack<T>::~Stack() {
   delete [] m_pT ;
}
        
template <class T> void Stack<T>::push(T t) {
    m_size++;
    m_pT[m_size - 1] = t;
    
}
template <class T> T Stack<T>::pop() {
    T t = m_pT[m_size - 1];
    m_size--;
    return t;
}
template <class T> bool Stack<T>::isEmpty() {
    return m_size == 0;
}
登入後複製

上述定義了一個類別模板​​--棧,這個棧很簡單,只是為了說明類別模板如何使用而已,最多只能支援100個元素入棧,使用範例如下:

//main.cpp
#include <stdio.h>
#include "stack.h"
int main() {
    Stack<int> intStack;
    intStack.push(1);
    intStack.push(2);
    intStack.push(3);
    
    while (!intStack.isEmpty()) {
        printf("num:%d\n", intStack.pop());
    }
    return 0;
}
登入後複製

模板參數
模板可以有類型參數,也可以有常規的型別參數int,也可以有預設模板參數,例如

template<class T, T def_val> class Stack{...}
登入後複製

上述類別模板的棧有一個限制,就是最多只能支援100個元素,我們可以使用模板參數來配置這個棧的最大元素數,如果不配置,就設定預設最大值為100,程式碼如下:

//statck.h
template <class T,int maxsize = 100> class Stack {
    public:
        Stack();
        ~Stack();
        void push(T t);
        T pop();
        bool isEmpty();
    private:
        T *m_pT;        
        int m_maxSize;
        int m_size;
};

#include "stack.cpp"
登入後複製
//stack.cpp
template <class T,int maxsize> Stack<T, maxsize>::Stack(){
   m_maxSize = maxsize;      
   m_size = 0;
   m_pT = new T[m_maxSize];
}
template <class T,int maxsize>  Stack<T, maxsize>::~Stack() {
   delete [] m_pT ;
}
        
template <class T,int maxsize> void Stack<T, maxsize>::push(T t) {
    m_size++;
    m_pT[m_size - 1] = t;
    
}
template <class T,int maxsize> T Stack<T, maxsize>::pop() {
    T t = m_pT[m_size - 1];
    m_size--;
    return t;
}
template <class T,int maxsize> bool Stack<T, maxsize>::isEmpty() {
    return m_size == 0;
}
登入後複製

使用範例如下:

//main.cpp
#include <stdio.h>
#include "stack.h"
int main() {
    int maxsize = 1024;
    Stack<int,1024> intStack;
    for (int i = 0; i < maxsize; i++) {
        intStack.push(i);
    }
    while (!intStack.isEmpty()) {
        printf("num:%d\n", intStack.pop());
    }
    return 0;
}
登入後複製

模板專門化

 當我們要定義模板的不同實現,我們可以使用模板的專門化

 當我們要定義模板的不同實現,我們可以使用模板的專門化

 當我們要定義模板的不同實現,我們可以使用模板的專門化

 當我們要定義模板的不同實現,我們可以使用模板的專門化

 當我們要定義模板的不同實現,我們可以使用模板的專門化

 當我們要定義模板的不同實現,我們可以使用模板的專門化。例如我們定義的stack類別模板,如果是char*類型的棧,我們希望可以複製char的所有資料到stack類別中,因為只是保存char指針,char指針指向的記憶體有可能會失效,stack彈出的堆疊元素char指針,指向的記憶體可能已經無效了。還有我們定義的swap函數模板,在vector或list等容器類型時,如果容器保存的物件很大,會佔用大量內存,性能下降,因為要產生一個臨時的大物件保存a,這些都需要模板的專門化才能解決。

函數模板專門化

  假設我們swap函數要處理一個情況,我們有兩個很多元素的vector,在使用原來的swap函數,執行tmpT = t1要拷貝t1的全部元素,佔用大量內存,造成性能下降,於是我們系統通過vector.swap函數解決這個問題,代碼如下:

//method.h
template<class T> void swap(T& t1, T& t2);

#include "method.cpp"
登入後複製
#include <vector>
using namespace std;
template<class T> void swap(T& t1, T& t2) {
    T tmpT;
    tmpT = t1;
    t1 = t2;
    t2 = tmpT;
}

template<> void swap(std::vector<int>& t1, std::vector<int>& t2) {
    t1.swap(t2);
}
登入後複製

template<>前綴表示這是一個專門化,描述時不用模板參數,使用範例如下:

//main.cpp
#include <stdio.h>
#include <vector>
#include <string>
#include "method.h"
int main() {
    using namespace std;
    //模板方法 
    string str1 = "1", str2 = "2";
    swap(str1, str2);
    printf("str1:%s, str2:%s\n", str1.c_str(), str2.c_str());  
    
    vector<int> v1, v2;
    v1.push_back(1);
    v2.push_back(2);
    swap(v1, v2);
    for (int i = 0; i < v1.size(); i++) {
        printf("v1[%d]:%d\n", i, v1[i]);
    }
    for (int i = 0; i < v2.size(); i++) {
        printf("v2[%d]:%d\n", i, v2[i]);
    }
    return 0;
}
登入後複製

vector的swap程式碼還是比較局限,如果要用模板專門化解決所有vector的swap,該如何做呢,只需要把下面程式碼

template<> void swap(std::vector<int>& t1, std::vector<int>& t2) {
    t1.swap(t2);
}
登入後複製

改為

就可以了,其他程式碼不變。

類模板專門化

 請看下面compare代碼:

template<class V> void swap(std::vector<V>& t1, std::vector<V>& t2) {
    t1.swap(t2);
}
登入後複製
//compare.h
template <class T>
 class compare
 {
  public:
  bool equal(T t1, T t2)
  {
       return t1 == t2;
  }
};
登入後複製

在比較兩個整數,compare的equal方法是正確的,但是compare的模板參數是char*時,這個模板就不能工作了,於是修改如下:

#include <iostream>
#include "compare.h"
 int main()
 {
  using namespace std;
  char str1[] = "Hello";
  char str2[] = "Hello";
  compare<int> c1;
  compare<char *> c2;   
  cout << c1.equal(1, 1) << endl;        //比较两个int类型的参数
  cout << c2.equal(str1, str2) << endl;   //比较两个char *类型的参数
  return 0;
 }
登入後複製

main.cpp檔案不變,此程式碼可以正常運作。

模板類型轉換

還記得我們自訂的Stack模板嗎,在我們的程式中,假設我們定義了Shape和Circle類,程式碼如下:

//compare.h
#include <string.h>
template <class T>
 class compare
 {
  public:
  bool equal(T t1, T t2)
  {
       return t1 == t2;
  }
};
   

template<>class compare<char *>  
{
public:
    bool equal(char* t1, char* t2)
    {
        return strcmp(t1, t2) == 0;
    }
};
登入後複製

然後我們希望可以這麼使用:

reee

這裡是無法編譯的,因為Stack不是Stack的父類,然而我們卻希望程式碼可以這麼工作,那我們就要定義轉換運算子了,Stack程式碼如下:

//shape.h
class Shape {

};
class Circle : public Shape {
};
登入後複製
//main.cpp
#include <stdio.h>
#include "stack.h"
#include "shape.h"
int main() {
    Stack<Circle*> pcircleStack;
    Stack<Shape*> pshapeStack;
    pcircleStack.push(new Circle);
    pshapeStack = pcircleStack;
    return 0;
}
登入後複製
登入後複製
//statck.h
template <class T> class Stack {
    public:
        Stack();
        ~Stack();
        void push(T t);
        T pop();
        bool isEmpty();
        template<class T2>  operator Stack<T2>();
    private:
        T *m_pT;        
        int m_maxSize;
        int m_size;
};

#include "stack.cpp"
登入後複製

這樣,Stack或Stack就可以自動轉換為Stack或Stack,如果轉換的型別是Stack到Stack,編譯器會報錯。

🎜其他🎜🎜一個類別沒有模板參數,但是成員函數有模板參數,是可行的,代碼如下:🎜
template <class  T>  Stack<T>::Stack(){
   m_maxSize = 100;      
   m_size = 0;
   m_pT = new T[m_maxSize];
}
template <class T>  Stack<T>::~Stack() {
   delete [] m_pT ;
}
        
template <class T> void Stack<T>::push(T t) {
    m_size++;
    m_pT[m_size - 1] = t;
    
}
template <class T> T Stack<T>::pop() {
    T t = m_pT[m_size - 1];
    m_size--;
    return t;
}
template <class T> bool Stack<T>::isEmpty() {
    return m_size == 0;
}

template <class T> template <class T2>  Stack<T>::operator Stack<T2>() {
    Stack<T2> StackT2;
    for (int i = 0; i < m_size; i++) {
        StackT2.push((T2)m_pT[m_size - 1]);
    }
    return StackT2;
}
登入後複製
🎜甚至可以把Util的equal聲明為static,代碼如下:🎜
//main.cpp
#include <stdio.h>
#include "stack.h"
#include "shape.h"
int main() {
    Stack<Circle*> pcircleStack;
    Stack<Shape*> pshapeStack;
    pcircleStack.push(new Circle);
    pshapeStack = pcircleStack;
    return 0;
}
登入後複製
登入後複製
🎜🎜🎜
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1321
25
PHP教程
1269
29
C# 教程
1249
24
透過Golang的Template套件實現資料視覺化 透過Golang的Template套件實現資料視覺化 Jul 17, 2023 am 09:01 AM

透過Golang的Template套件實現資料視覺化隨著大數據時代的到來,資料視覺化成為了資訊處理和分析的重要手段之一。數據視覺化能夠以簡潔直觀的方式展現數據,幫助人們更好地理解和分析數據。在Golang中,我們可以使用Template套件來實現資料視覺化功能。本文將介紹如何利用Golang的Template套件實現資料視覺化,並提供程式碼範例。 Golang的Tem

Golang和Template套件:建立個人化的使用者介面 Golang和Template套件:建立個人化的使用者介面 Jul 18, 2023 am 10:27 AM

Golang和Template套件:創造個人化的使用者介面在現代的軟體開發中,使用者介面往往是使用者與軟體互動的最直接的途徑。為了提供一個好用、美觀的使用者介面,開發者需要靈活的工具來建立和自訂使用者介面。而在Golang中,開發者可以使用Template套件來實現這一目標。本文將介紹Golang和Template套件的基本用法,並透過程式碼範例展示如何建立個人化的使用者界

如何解決 golang 中的 'undefined: template.Must' 錯誤? 如何解決 golang 中的 'undefined: template.Must' 錯誤? Jun 24, 2023 pm 09:00 PM

Go語言是一種越來越受歡迎的程式語言,它的語法簡潔,效能高效,易於開發。 Go語言中提供了強大的模板引擎-"text/template",但是在使用時,有些人可能會遇到"undefined:template.Must"的錯誤,以下是解決該錯誤的方法。導入正確的套件在使用"text/template"模板引擎時,需要導入"text/templat

Golang的Template套件:開發高效能的網路應用 Golang的Template套件:開發高效能的網路應用 Jul 17, 2023 pm 05:29 PM

Golang的Template套件:開發高效能的網頁應用程式引言:在網路開發中,模板引擎是一個非常重要的元件。它允許開發者將動態的資料與靜態的HTML模板結合,以產生最終的網頁內容。 Golang的Template套件提供了一種高效且強大的方式來處理模板。本文將介紹Golang的Template套件的基本用法,並透過一些程式碼範例展示如何使用它來開發高效能的Web應

Golang和Template套件:建立強大的前端開發工具箱 Golang和Template套件:建立強大的前端開發工具箱 Jul 19, 2023 pm 02:43 PM

Golang和Template套件:建立強大的前端開發工具箱在當今的軟體開發中,前端開發在整個專案中變得越來越重要。為了提供一個優雅且可靠的前端開發解決方案,我們可以使用Golang語言和其內建的Template套件。本文將介紹如何使用Golang和Template套件來建立一個強大的前端開發工具箱。一、Golang:高效且易於使用的程式語言Golang是一種現代

使用Golang的Template套件建立現代化的網站 使用Golang的Template套件建立現代化的網站 Jul 19, 2023 am 09:22 AM

使用Golang的Template套件建立現代化的網站近年來,隨著網路的快速發展,越來越多的網站需要提供個人化的內容和介面。同時,Golang(又稱Go語言)以其高效能和強大的並發能力成為了開發網路應用的熱門選擇。在Golang的標準函式庫中,提供了一套強大且靈活的模板引擎,即Template套件。本文將介紹如何使用Golang的Template套件建構現代化

Golang和Template套件:快速開發方便的前端介面 Golang和Template套件:快速開發方便的前端介面 Jul 17, 2023 pm 08:57 PM

Golang與Template套件:快速開發便利的前端介面在現代Web開發中,前端介面的開發是重要且不可或缺的環節。前端介面的設計不僅需要美觀,還需要具備良好的使用者體驗。然而,傳統的前端開發過程往往需要耗費大量的時間和精力。幸運的是,Golang提供了Template包,旨在幫助開發人員快速建立便利的前端介面。 Golang是一種高效率、簡潔、並發、靜態型別的

RedisTemplate之opsForValue如何使用 RedisTemplate之opsForValue如何使用 Jun 03, 2023 am 08:55 AM

Redis中opsForValue()方法的使用1、set(Kkey,Vvalue)新增一個字串型別的值,key是鍵,value是值。 redisTemplate.opsForValue().set("stringValue","bbb");2、get(Objectkey)取得key鍵對應的值。 StringstringValue=redisTemplate.opsForValue().get("key")3、append(Kkey,St

See all articles