c 模板編譯

2021-07-23 04:10:26 字數 2732 閱讀 9894

如何組織編寫模板程式

前言 常遇到詢問使用模板到底是否容易的問題,我的回答是:「模板的使用是容易的,但組織編寫卻不容易」。看看我們幾乎每天都能遇到的模板類吧,如stl, atl, wtl, 以及boost的模板類,都能體會到這樣的滋味:介面簡單,操作複雜。

我在5年前開始使用模板,那時我看到了mfc的容器類。直到去年我還沒有必要自己編寫模板類。可是在我需要自己編寫模板類時,我首先遇到的事實卻是 「傳統」程式設計方法(在.h檔案宣告,在.cpp檔案中定義)不能用於模板。於是我花費一些時間來了解問題所在及其解決方法。

本文物件是那些熟悉模板但還沒有很多編寫模板經驗的程式設計師。本文只涉及模板類,未涉及模板函式。但論述的原則對於二者是一樣的。

問題的產生

通過下例來說明問題。例如在array.h檔案中有模板類array:

// array.h

template

class

array

; t& operator(int i)

const t& get_elem (int i) const

void set_elem(int i, const t& value)

operator t*()

};

然後在main.cpp檔案中的主函式中使用上述模板:

// main.cpp

#include "array.h"

int main(void)

這時編譯和執行都是正常的。程式先建立乙個含有50個整數的陣列,然後設定陣列的第乙個元素值為2,再讀取第乙個元素值,最後將指標指向陣列起點。

但如果用傳統程式設計方式來編寫會發生什麼事呢?我們來看看:

將array.h檔案**成為array.h和array.cpp二個檔案(main.cpp保持不變)

// array.h        

template

class

array

; t& operator(int i);

const t& get_elem (int i) const;

void set_elem(int i, const t& value);

operator t*();

};

// array.cpp

#include "array.h"

template

t& array

::operator (int i)

template

const t& array

::get_elem(int i) const

template

void

array

::set_elem(int i, const t& value)

template

array

::operator t*()

要回答上面的問題,就要深入了解模板的例項化過程。

模板例項化

程式設計師在使用模板類時最常犯的錯誤是將模板類視為某種資料型別。所謂型別參量化(parameterized types)這樣的術語導致了這種誤解。模板當然不是資料型別,模板就是模板,恰如其名:

編譯器使用模板,通過更換模板引數來建立資料型別。這個過程就是模板例項化(instantiation)。

從模板類建立得到的型別稱之為特例(specialization)。

模板例項化取決於編譯器能夠找到可用**來建立特例(稱之為例項化要素,

point of instantiation)。

要建立特例,編譯器不但要看到模板的宣告,還要看到模板的定義。

模板例項化過程是遲鈍的,即只能用函式的定義來實現例項化。

再回頭看上面的例子,可以知道array是乙個模板,array

// templateinstantiations.cpp                

#include "array.cpp"

template

class

array

; // 顯式例項化

array型別不是在main.cpp中產生,而是在templateinstantiations.cpp中產生。這樣鏈結器就能夠找到它的定義。用這種方法,不會產生巨大的標頭檔案,加快編譯速度。而且標頭檔案本身也顯得更加「乾淨」和更具有可讀性。但這個方法不能得到惰性例項化的好處,即它將顯式地生成所有的成員函式。另外還要維護templateinstantiations.cpp檔案。

第三種方法是在模板定義中使用export關鍵字,剩下的事就讓編譯器去自行處理了。當我在

stroustrup的書中讀到export 時,感到非常興奮。但很快就發現vc 6.0不支援它,後來又發現根本沒有編譯器能夠支援這個關鍵字(第乙個支援它的編譯器要在2023年底才問世)。自那以後,我閱讀了不少關於export 的文章,了解到它幾乎不能解決用包含模式能夠解決的問題。欲知更多的export關鍵字,建議讀讀herb sutter撰寫的文章。

結論 要開發模板庫,就要知道模板類不是所謂的」原始型別」,要用其它的程式設計思路。本文目的不是要嚇唬那些想進行模板程式設計的程式設計師。恰恰相反,是要提醒他們避免犯下開始模板程式設計時都會出現的錯誤。

本文**:

C 模板編譯問題

今天做乙個矩陣類,打算使用模板,結果出現了問題。問題描述 像往常一樣在matrix.h檔案中定義了乙個模板類,如下 template class matrix matrix 在matrix.cpp檔案中定義類成員函式,如下 template matrix matrix 編譯不通過 最後找到解決辦法,...

C 模板編譯模型

編譯器只有在用到模板時,如呼叫了函式模板或呼叫了類模板的物件的時候,編譯器才產生特定型別的模板例項。編譯時,模板與普通函式 類的區別 標準 c 編譯模板 的兩種模型 包含編譯 分別編譯 相同點 構造程式的方式相同 類定義和函式宣告放在標頭檔案中,而函式定義和成員定義放在原始檔中。不同點 編譯器怎樣使...

C 模板分離編譯

乙個程式 專案 由若干個原始檔共同實現,而每個原始檔單獨編譯生成目標檔案,最後將所有目標檔案鏈結起來形成單一的可執行檔案的過程稱為分離編譯模式。假如有以下場景,模板的宣告與定義分離開,在標頭檔案中進行宣告,原始檔中完成定義 a.h template class t t add const t lef...