1. 程式人生 > >C++ 模板

C++ 模板

出現 string copy 根據 設計 template nbsp 調用 四種

泛型程序設計與模板:
一種算法在實現時不指定具體要操作的數據的類型的程序設計方法。所謂"泛型"是指算法只要實現
一遍,就能適用於多種數據類型。泛型程序設計方法的好處在於能夠減少重復代碼的編寫。

在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++ 模板