青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

旅途

如果想飛得高,就該把地平線忘掉

如何組織編寫模板程序 轉

前兩天遇到一個問題, 第一反應是用模板類來解決是最好的,所以就動手寫了一個類.
但寫完才發現會在編譯器鏈接的時候報錯,百思不得其解,上網一頓搜羅,發現下文,終于解決了我的問題.同時我也對模板類有了進一步的理解.

[轉]
前言
常遇到詢問使用模板到底是否容易的問題,我的回答是:“模板的使用是容易的,但組織編寫卻不容易”??纯次覀儙缀趺刻於寄苡龅降哪0孱惏?,如STL, ATL, WTL, 以及Boost的模板類,都能體會到這樣的滋味:接口簡單,操作復雜。

我在5年前開始使用模板,那時我看到了MFC的容器類。直到去年我還沒有必要自己編寫模板類。可是在我需要自己編寫模板類時,我首先遇到的事實卻是“傳統”編程方法(在*.h文件聲明,在*.cpp文件中定義)不能用于模板。于是我花費一些時間來了解問題所在及其解決方法。

本文對象是那些熟悉模板但還沒有很多編寫模板經驗的程序員。本文只涉及模板類,未涉及模板函數。但論述的原則對于二者是一樣的。

問題的產生
通過下例來說明問題。例如在array.h文件中有模板類array:
// array.h
template <typename T, int SIZE>
class array
{
T data_[SIZE];
array (const array& other);
const array& ōperator = (const array& other);
public:
array(){};
T& operator[](int i) {return data_[i];}
const T& get_elem (int i) const {return data_[i];}
void set_elem(int i, const T& value) {data_[i] = value;}
operator T*() {return data_;}
};
然后在main.cpp文件中的主函數中使用上述模板:
// main.cpp
#include "array.h"

int main(void)
{
array<int, 50> intArray;
intArray.set_elem(0, 2);
int firstElem = intArray.get_elem(0);
int* begin = intArray;
}
這時編譯和運行都是正常的。程序先創建一個含有50個整數的數組,然后設置數組的第一個元素值為2,再讀取第一個元素值,最后將指針指向數組起點。

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

將array.h文件分裂成為array.h和array.cpp二個文件(main.cpp保持不變)
// array.h
template <typename T, int SIZE>
class array
{
T data_[SIZE];
array (const array& other);
const array& ōperator = (const array& other);
public:
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<typename T, int SIZE> T& array<T, SIZE>::operator [](int i)
{
return data_[i];
}

template<typename T, int SIZE> const T& array<T, SIZE>::get_elem(int i) const
{
return data_[i];
}

template<typename T, int SIZE> void array<T, SIZE>::set_elem(int i, const T& value)
{
data_[i] = value;
}
template<typename T, int SIZE> array<T, SIZE>::operator T*()
{
return data_;
}
編譯時會出現3個錯誤。問題出來了:
為什么錯誤都出現在第一個地方?
為什么只有3個鏈接出錯?array.cpp中有4個成員函數。
要回答上面的問題,就要深入了解模板的實例化過程。

模板實例化
程序員在使用模板類時最常犯的錯誤是將模板類視為某種數據類型。所謂類型參量化(parameterized types)這樣的術語導致了這種誤解。模板當然不是數據類型,模板就是模板,恰如其名:

編譯器使用模板,通過更換模板參數來創建數據類型。這個過程就是模板實例化(Instantiation)。
從模板類創建得到的類型稱之為特例(specialization)。
模板實例化取決于編譯器能夠找到可用代碼來創建特例(稱之為實例化要素,
point of instantiation)。
要創建特例,編譯器不但要看到模板的聲明,還要看到模板的定義。
模板實例化過程是遲鈍的,即只能用函數的定義來實現實例化。


再回頭看上面的例子,可以知道array是一個模板,array<int, 50>是一個模板實例 - 一個類型。從array創建array<int, 50>的過程就是實例化過程。實例化要素體現在main.cpp文件中。如果按照傳統方式,編譯器在array.h文件中看到了模板的聲明,但沒有模板的定義,這樣編譯器就不能創建類型array<int, 50>。但這時并不出錯,因為編譯器認為模板定義在其它文件中,就把問題留給鏈接程序處理。

現在,編譯array.cpp時會發生什么問題呢?編譯器可以解析模板定義并檢查語法,但不能生成成員函數的代碼。它無法生成代碼,因為要生成代碼,需要知道模板參數,即需要一個類型,而不是模板本身。

這樣,鏈接程序在main.cpp 或 array.cpp中都找不到array<int, 50>的定義,于是報出無定義成員的錯誤。

至此,我們回答了第一個問題。但還有第二個問題,在array.cpp中有4個成員函數,鏈接器為什么只報了3個錯誤?回答是:實例化的惰性導致這種現象。在main.cpp中還沒有用上operator[],編譯器還沒有實例化它的定義。

解決方法
認識了問題,就能夠解決問題:
在實例化要素中讓編譯器看到模板定義。
用另外的文件來顯式地實例化類型,這樣鏈接器就能看到該類型。
使用export關鍵字。

前二種方法通常稱為包含模式,第三種方法則稱為分離模式。

第一種方法意味著在使用模板的轉換文件中不但要包含模板聲明文件,還要包含模板定義文件。在上例中,就是第一個示例,在array.h中用行內函數定義了所有的成員函數?;蛘咴趍ain.cpp文件中也包含進array.cpp文件。這樣編譯器就能看到模板的聲明和定義,并由此生成array<int, 50>實例。這樣做的缺點是編譯文件會變得很大,顯然要降低編譯和鏈接速度。

第二種方法,通過顯式的模板實例化得到類型。最好將所有的顯式實例化過程安放在另外的文件中。在本例中,可以創建一個新文件templateinstantiations.cpp:
// templateinstantiations.cpp
#include "array.cpp"

template class array <int, 50>; // 顯式實例化
array<int, 50>類型不是在main.cpp中產生,而是在templateinstantiations.cpp中產生。這樣鏈接器就能夠找到它的定義。用這種方法,不會產生巨大的頭文件,加快編譯速度。而且頭文件本身也顯得更加“干凈”和更具有可讀性。但這個方法不能得到惰性實例化的好處,即它將顯式地生成所有的成員函數。另外還要維護templateinstantiations.cpp文件。

第三種方法是在模板定義中使用export關鍵字,剩下的事就讓編譯器去自行處理了。當我在
Stroustrup的書中讀到export時,感到非常興奮。但很快就發現VC 6.0不支持它,后來又發現根本沒有編譯器能夠支持這個關鍵字(第一個支持它的編譯器要在2002年底才問世)。自那以后,我閱讀了不少關于export的文章,了解到它幾乎不能解決用包含模式能夠解決的問題。欲知更多的export關鍵字,建議讀讀Herb Sutter撰寫的文章。

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

posted on 2007-10-06 00:42 旅途 閱讀(183) 評論(0)  編輯 收藏 引用 所屬分類: C/C++

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产专区欧美精品| 亚洲香蕉伊综合在人在线视看| 狠狠干综合网| 亚洲国产成人不卡| 国产精品久久久久久久一区探花| 久久精品国产久精国产爱| 欧美激情精品久久久六区热门 | 亚洲欧美成人精品| 蜜臀av在线播放一区二区三区| 亚洲黄页一区| 久久精品在线观看| 久久嫩草精品久久久久| 国产欧美一二三区| 亚洲一区二区三区国产| 亚洲一区二区免费看| 欧美国产精品人人做人人爱| 在线一区欧美| 欧美久久久久免费| 亚洲国产成人porn| 亚洲人成在线播放网站岛国| 亚洲欧美bt| 日韩视频精品在线| 欧美日韩p片| 宅男精品导航| 欧美在线综合视频| 国产在线一区二区三区四区| 久久久久久尹人网香蕉| 欧美大片免费观看| 日韩视频三区| 欧美午夜美女看片| 亚洲综合大片69999| 久久精品国产在热久久| 一区国产精品| 欧美日韩1区| 欧美激情精品久久久久久黑人| 欲香欲色天天天综合和网| 欧美一区精品| 欧美超级免费视 在线| 羞羞色国产精品| 国产亚洲网站| 久久中文字幕一区| 欧美大尺度在线| 欧美成人69av| 欧美色大人视频| 亚洲精品久久久蜜桃| 最新国产成人在线观看| 欧美在线在线| 亚洲日本中文字幕| 久久激情视频久久| 美女精品网站| 亚洲精品一区二区三区婷婷月| 亚洲国产欧美在线人成| 国产欧美一区二区精品秋霞影院| 国产一区二区久久久| 久久精品日韩欧美| 亚洲一二三区视频在线观看| 欧美小视频在线观看| 亚洲视频一区在线| 久久久午夜视频| 一区二区三区视频在线播放| 国产亚洲精品久| 欧美人与性动交cc0o| 欧美亚洲午夜视频在线观看| 久久阴道视频| 午夜精品久久久久久久99黑人| 国产亚洲高清视频| 免费久久99精品国产自| 99www免费人成精品| 亚洲一级在线| 国内精品久久久久久| 欧美四级伦理在线| 久久综合影视| 亚洲成色777777在线观看影院| 欧美亚洲尤物久久| 老牛嫩草一区二区三区日本| 国产一区视频观看| 亚洲美女av在线播放| 欧美另类videos死尸| 久久久综合精品| 久久久久国产精品厨房| 美女尤物久久精品| 亚洲国产成人精品久久| 亚洲国产美国国产综合一区二区| 欧美肥婆在线| 一区二区久久| 亚洲伦理网站| 久久亚洲风情| 亚洲精品乱码久久久久久| 嫩草影视亚洲| 久久亚洲私人国产精品va| 亚洲欧洲一区二区三区| 国产伦精品一区二区三区视频孕妇| 免费日韩精品中文字幕视频在线| 99亚洲一区二区| 国产一区深夜福利| 亚洲免费视频观看| 亚洲大片精品永久免费| 亚洲美女精品久久| 国产精品国产亚洲精品看不卡15| 亚洲午夜电影| 老鸭窝亚洲一区二区三区| 99精品免费视频| 久久亚洲春色中文字幕| 久久乐国产精品| 在线精品一区二区| av成人国产| 久久精品人人做人人爽| 国产精品羞羞答答| 在线精品国产成人综合| 久久久久久久波多野高潮日日| 欧美一区=区| 一区在线免费| 一本一本久久a久久精品牛牛影视| 欧美激情亚洲视频| 亚洲一区二区3| 亚洲嫩草精品久久| 狠久久av成人天堂| 日韩视频亚洲视频| 国产日本欧美一区二区| 欧美激情在线观看| 欧美成人一区二区三区在线观看| 欧美高清视频| 欧美va亚洲va香蕉在线| 久久夜色精品国产| 91久久视频| 欧美一级视频精品观看| 国产精品久久9| 韩国av一区二区三区| 亚洲欧美日韩在线综合| 日韩亚洲成人av在线| 欧美国产欧美综合| 亚洲欧洲一二三| 欧美成年人视频| 久久久精品性| 韩国av一区二区三区在线观看| 欧美专区在线观看一区| 亚洲女爱视频在线| 国产视频欧美视频| 久久久www成人免费无遮挡大片| 亚洲午夜国产成人av电影男同| 欧美精品高清视频| 一本色道久久综合一区| 9久re热视频在线精品| 欧美新色视频| 欧美在线观看视频| 欧美亚洲专区| 韩国福利一区| 欧美 亚欧 日韩视频在线| 免费试看一区| 在线性视频日韩欧美| 欧美99久久| 久久午夜电影| 亚洲精品日韩激情在线电影| 亚洲第一黄色| 欧美日本一区二区视频在线观看| 日韩一区二区高清| 日韩手机在线导航| 国产精品你懂的| 久久这里只有| 欧美激情网站在线观看| 亚洲电影免费在线观看| 欧美精品二区三区四区免费看视频| 羞羞色国产精品| 99精品视频一区二区三区| 久久久综合网站| 亚洲精品免费在线| 日韩一级免费观看| 国产日韩一区二区| 老司机精品福利视频| 欧美成人在线影院| 亚洲一区二区三区国产| 久久精品91| 一区二区三区四区五区视频 | 欧美专区在线播放| 久久综合色综合88| 亚洲天堂成人在线观看| 性欧美在线看片a免费观看| 国产欧美日韩视频一区二区| 亚洲高清久久久| 亚洲专区在线| 久久精品亚洲一区二区三区浴池 | 亚洲精品在线一区二区| 国产欧美一区二区精品秋霞影院| 国产精品午夜视频| 久久男人资源视频| 欧美日本精品| 久久久www成人免费无遮挡大片| 久久久精品午夜少妇| 一区二区日韩伦理片| 欧美一区二区三区在线免费观看| 亚洲伦理在线免费看| 欧美一区二区三区四区在线观看| 亚洲精品中文字幕有码专区| 午夜免费在线观看精品视频| 在线观看欧美一区| 欧美一级夜夜爽| 亚洲婷婷在线| 欧美fxxxxxx另类| 久久激情视频| 国产精品中文字幕在线观看|