標籤:++ 包括 log pen 編寫 static temp 指定 自動類型轉換
泛型程式設計與模板:
一種演算法在實現時不指定具體要操作的資料的類型的程式設計方法。所謂"泛型"是指演算法只要實現
一遍,就能適用於多種資料類型。泛型程式設計方法的好處在於能夠減少重複代碼的編寫。
在C++中模板分為函數模板和類模板兩種。
函數模板:
作用:物件導向的繼承和多態機制有效提高了程式的可重用性和可擴充性,但在可重用性的
某些方面,程式員還希望得到更多的支援,以減少重複代碼的編寫。
// 例如:Swap函數void Swap(int &a, int &b){ int c = a; a = b; b = c;} void Swap(double &a, double &b){ double c = a; a = b; b = c;}template <typename T>void Swap(T &a, T &b){ T c = a; a = b; b = c;}
在編寫Swap函數時,在面對不同的資料類型,我們需要編寫不同的重載函數,但這些函數初處了所處理的
資料類型的不同,形式上是一模一樣的,為了減少這些重複代碼的編寫,繼承和多態明顯無法解決這些問
題。因此,"模板"的概念就應運而生。
函數模板的寫法:
template <typename 型別參數1,型別參數2,...>
傳回值類型 模板名(形參表){
函數體;
}
typename關鍵字也可以用class關鍵字代替。
函數模板的原理:
編譯器由模板自動產生函數時(執行個體化),會用具體的類型名對模板中所有的型別參數進行替換,其他
部分則原封不動的保留。同一個型別參數只能替換為同一種類型。編譯器在編譯到調用函數模板的語
句時,會根據實參的類型判斷該如何替換模板中的型別參數。
編譯器由模板自動產生函數(類)的過程叫做模板的執行個體化。有模板執行個體化產生的函數(類)叫做模板函數(類)。
在函數模板中,型別參數不但可以用來定義參數的類型,還能用於定義局部變數和函數模板的傳回值。
#include<iostream> using namespace std;template <typename T>void Swap(T &a, T &b){ T c = a; a = b; b = c;}int main(){ int a = 3, b = 4; double c = 3.0, d = 4.0; Swap(a, b); // 執行個體化為 void Swap(int &a, int &b)函數 Swap(c, d); // 執行個體化為 void Swap(double &a, double &b)函數 return 0;}
編譯器對模板進行執行個體化時,並非只能通過模板調用語句的實參來執行個體化模板中的型別參數,模板調用語句
可以明確指明要把型別參數執行個體化為哪種類型。
模板名<實際型別參數1,實際型別參數2,...>
例如:Swap<double, double>(a, b);
當有多個函數和函數模板名字相同的情況下,一條函數調用語句的匹配順序:
1.先找到參數完全符合的普通函數
2.再找參數完全符合的模板函數
3.再找實參經過自動類型轉換後能匹配的普通函數
4.如果以上情況都無法找到,則報錯
類模板:
類模板的寫法:
template <型別參數表>
class 類模板名{
成員函數和成員變數;
};
型別參數表的寫法:
class 型別參數1,class 型別參數2,...
類模板中的成員函數放到類模板外面定義時的寫法:
template <型別參數表>
傳回值類型 類模板名<型別參數名列表>::成員函數名(參數表){
...
}
用類模板定義對象的寫法如下:
類模板名<真是型別參數表> 對象名(建構函式實際參數表);
可以將函數模板當做類模板的成員函數,成員函數模板只有在被調用時才會被執行個體化。
類模板的型別參數表中可以出現非型別參數
template <class T, int size>
class Carry{
};
類模板和類模板之間類模板和類之間可以相互繼承,它們之間的派生關係有以下四種:
1.類模板 從 類模板 派生
2.類模板 從 模板類 派生
3.類模板 從 普通類 派生
4.普通類 從 模板類 派生
函數、類、類的成員函數、函數模板、類模板、類模板的成員函數都可以作為類模板的友元。
類模板中可以定義靜態成員,給定執行個體化得到的所有對象共用一個靜態成員。
template <class T> class Foo{
...
static int i;
}
即Foo<int>共用一個static int i,Foo(string)共用一個static int i。
當需要在多個檔案中用到同一個模板,則可以將該模板的全部內容(包括類模板的成員函數的函
數體)都寫在一個標頭檔中,然後在多個.cpp檔案中包含,而不用擔心重複定義的問題。
// 樣本template <class Type> class QueueItem{ QueueItem(const Type &t):item(t), next(0){ } Type item; QueueItem *next;}; template <class Type> class Queue{ private: QueueItem<Type> *head; QueueItem<Type> *tail; void destory(); void copy_elems(const Queue&); public: Queue():head(0), tail(0){ } Queue(const Queue &Q):head(0), tail(0){ copy_elems(Q); } Queue& operator=(const Queue&); ~Queue(){ destory(); } Type& front(){ return head->item; } const Type& front() const { return head->item; } void push(const Type &); void pop(); bool empty() const { return head == 0; }};
C++ 範本