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

woaidongmao

文章均收錄自他人博客,但不喜標題前加-[轉貼],因其丑陋,見諒!~
隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
數據加載中……

c++模板基礎

只有使用C++語言的少數用戶才努力嘗試去理解模板的基本原理。然而那些希望去探索更多高級用法的人往往發現自己需要努力去理解模板是如何被語言所支持的,因為缺乏明確的說明。一個很大的問題在于一些工具只實現了C++標準的一個子集。本文將指出它們共同的缺陷并深入剖析如何使用C++模板快速產生可重用和高效的代碼。

模板功能應用的典型是通過一系列模板類形成的完整類庫,特別是STL和ATL。標準C++庫(STL)提供了很多可重用和靈活的類及算法,而ATL則是使用C++進行COM編程的事實標準。要掌握這些及其它的模板庫,理解模板是如何工作的這一基礎是非常重要的。

函數模板

int main()
{
    0 cout<<add(2,3)<<endl;
    1 cout<<add(2.1,3)<<endl;
    2 cout<<add(2,3.2)<<endl;
    3 cout<<add(2.2,3.3)<<endl;
    4 cout<<add("hello eone ","world")<<endl;
    return 0;
}

     也可以通過宏定義#define add(a,b) ((a)+(b))來實現,但是指針(字符串)不能直接相加.對于2,3,4需要進行模板特化.

通過重載函數,我們能夠完成多種不同數據類型的相同操作。要實現兩個double數值的加法和兩個整數類型的加法,我們可以使用一個重載函數:

int add(const int x, const int y)

{

return x + y;

}

double add(const double x, const double y)

{

return x + y;

}

這時,編譯器將根據它們的參數正確地解決這一問題。

// 調用int add(const int, const int);

const int z1 = add(3, 2);

// 調用double add(const double, const double);

const double z2 = add(3.0, 2.0);

如果我們需要處理其它類型,我們就不得不提供其他函數重載。對每個不同的數據類型實現一個函數重載,它們都遵循相同的模式,每當我們需要調用針對某一數據類型的函數時,原則上編譯器為我們生成相應的代碼。而一個模板函數則以如下方式實現:

template<class T>

const T add(const T &t1, const T &t2)

{

return t1 + t2;

}

從概念上來說,編譯器通過模板關鍵字(后面跟隨著模板由一或多個模板參數構成的參數列表)來識別模板。當為某一具體類型調用add時,編譯器將根據模板定義并用給定的類型替換出現在模板中的參數。在這個例子中,模板參數列表由一個獨立的類型模板參數T構成。使用一個模板函數替代函數重載,編譯器可以自動為所需的新類型生成代碼

我們可以對任何擁有+操作符定義的類型使用add模板。假設一個自定義的String類提供了字符串連接并知道如何將自身寫入到std::ostream。因為String與該模板函數兼容,因此我們可以調用它來實現字符串相加:

// 示例字符串

const string strBook("book");

const string strWorm("worm");

// 顯示 "bookworm".

cout << add(strBook, strWorm) << endl;

Seeing that we intended to add two String values, the compiler will generate the appropriate add function on our behalf, which would look something like:

const String add(const String &t1, const String &t2)

{

return t1 + t2;

}

顯式實例化

調用模板函數時,編譯器將先把正確的類型實例化模板。雖然標準允許顯式模板實例化,然而并非所有廠商都能夠正確地實例它。例如,Visual C++ 6.0 會潛在地調用錯誤的函數::

template<class T>

int getSize(void) {

return sizeof(T);

}

// 輸出4,應該為8

cout << "double: " << getSize<double>() << endl;

// 輸出4,正確

cout << "int: " << getSize<int>() << endl;

跨平臺代碼設計者不希望依賴于顯式模板函數實例化,除非有更好的編譯器能夠對它提供有效的支持

 

 

類似于函數模板,模板也可以應用于類。模板可以用于根據普通模式提供一系列類。如果我們需要一套完整的算術運算來補充add函數,我們可以考慮使用一個類。通過模板,它就可以根據類型參數化為一個普通類:

template<class T>

class CCalculator

{

public:

CCalculator(const T &x, const T &y) : m_x(x), m_y(y){ }

~CCalculator(void){ }

const T add(void){ return m_x + m_y; }

const T sub(void){ return m_x - m_y; }

const T mult(void){ return m_x * m_y; }

const T div(void){ return m_x / m_y; }

private:

const T m_x;

const T m_y;

};

要實例化模板類,我們需要提供一個指定類型:

// 創建一個整數計算對象

CCalculator<int> calc(5, 2);

// 結果應該為 10

const int z = calc.mult();

如函數模板一樣,編譯器為模板不同類型的引用創建不同的類。這為代碼重用提供了一個強大的機制,允許單個模板用于任何兼容的數據類型

模板編輯模型

在編寫模板類時,函數定義通常與它們的聲明一起保存在頭文件中,而不使用另外的.cpp文件。否則可能會導致鏈接錯誤。這是因為大多數編譯器要求模板定義在以頭文件為單位的轉譯單元中有效

這個行為的原因是模板只是一個模式,同樣它們不直接產生代碼(直到編譯器遇到一個應用實例)。如果我們創建一個CCalculator<int> 實例并調用其中的某個類方法,編譯器將需要找到函數定義。如果頭文件中包含了該定義則一切都會是正確的。但是如果定義存在于.cpp文件中,編譯器不能期望在此時找到匹配的模式并利用其產生所需的代碼。然而,C++標準提供了一個機制對編譯器進行輔助。Export關鍵字可以使通知編譯器我們提供了一個分離的編輯模板:

// MyTemplateFunction.h

template<class T>

void myTemplateFunction(const T &t1);

// MyTemplateFunction.cpp

export template <class T>

void myTemplateFunction(const T &t1)

{

...

}

現在,大多數編譯器要求模板定義通過頭文件包含被顯式添加到轉譯單元,雖然標準期望能夠獨立定義于.cpp文件中。這兩個不同的模板編輯模型即為包含模型和分離模型。在編寫時,我所知的支持分離模型的唯一的編譯器是Comeau C++。Comeau 的使用了不少方法來實現對標準中所定義的export關鍵字用法,但目前也還只是beta版本而已

typename關鍵字

另一個與模板相關的關鍵字是typename關鍵字,它有兩種用法。參數下面的模板類:

template<class T>

void myFunction(void)

{

// 這里可能會有問題

T::x1 * x2;

}

初次講到的時候可能會以為myFunction聲明了一個T::x1類型的指針變量x2。然而,這個函數也能夠表示類T的成員變量x1與全局變量x2的二進制乘法操作。使用typename關鍵字可以告訴編譯器某個未知標識符是一個類型:

// T:x1 是一個類型,而x2是一個指針

typename T:x1* x2;

第二種用法是在指定模板參數時替換class關鍵字:

// 下面的兩種方法是等效的...

template<class T1, class T2>;

template<typename T1, typename T2>;

標準允許以上任意一種方法,它們都是合法的。

成員函數模板

除了全局模板函數外,語言也支持成員模板函數:一個類可以擁有帶有模板參數列表的成員函數。參考下面的非模板類,它的構造函數被模板化:

class CTypeSize

{

public:

template<class T>

CTypeSize(const T &t1) :

m_nSize(sizeof(t1))

{

}

~CTypeSize(void){ };

int getSize(void) const{ return m_nSize; }

private:

const int m_nSize;

};

當模板成員函數被調用時,編譯器使用模板模式為給定類型生成代碼。這種情況下,我們能夠使用任意類型變量創建一個CtypeSize實例:

// 顯示12

CTypeSize t1("Hello World");

cout << t1.getSize() << endl;

// 在VC++6/Win32中顯示8

CTypeSize t2(7.0);

cout << t2.getSize() << endl;

某些時候,成員模板是實現拷貝構造函數最有效的方法,參考一個只有一個交易會的簡單容器類:

template<class T>

class CSingle

{

public:

CSingle(const T &t1) : m_Value(t1) { }

~CSingle(void){ }

T m_Value;

};

它導致下面的問題:

// 創建一個整數容器

CSingle<int> x(7);

// 這里需要一個拷貝構造...

CSingle<double> y(x);

通過使用成員模板,拷貝構造就能夠輕松完成:

template<class S>

CSingle(const CSingle<S> &s1) : m_Value(s1.m_Value) { }

當編輯器能夠將類型T的實例轉換為類型S時,這是可行的;這是因為double可以從一個整數構造。

總結

模板是C++的一個強大特征,它允許從數據類型中抽象出算法。本文介紹了模板定義和實例化的基礎,包括函數、類及成員模板的區別。

posted on 2008-09-01 12:10 肥仔 閱讀(679) 評論(0)  編輯 收藏 引用 所屬分類: 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>
            国产精品国产三级国产aⅴ入口| 久久精品一区中文字幕| 久久亚洲精品一区二区| 久久精品综合一区| 亚洲电影在线免费观看| 亚洲黄色高清| 欧美激情一区二区三区在线视频观看| 在线观看精品视频| 亚洲视频精品| 亚洲大片精品永久免费| 99综合电影在线视频| 国产亚洲欧美日韩在线一区| 欧美激情小视频| 国产欧美日韩不卡免费| 亚洲人午夜精品| 国产一区二区三区丝袜| 亚洲调教视频在线观看| 在线观看日韩一区| 欧美亚洲免费在线| 午夜精品久久久久久久99黑人| 久久精品国产久精国产一老狼| 亚洲欧美日韩国产成人| 欧美日韩三区| 亚洲精品国产日韩| 亚洲乱码国产乱码精品精98午夜| 亚洲欧美日韩一区二区在线 | 欧美成人午夜视频| 噜噜噜噜噜久久久久久91| 国产精品久久久久9999吃药| 91久久国产综合久久蜜月精品| 国产亚洲一区二区三区| 亚洲欧美在线播放| 久久久久欧美精品| 亚洲高清视频一区| 欧美丰满少妇xxxbbb| 亚洲国产第一页| 亚洲精品系列| 国产精品女人毛片| 欧美一区二区在线视频| 美日韩精品免费观看视频| 在线看欧美日韩| 欧美三级小说| 性做久久久久久久免费看| 久久精品国产亚洲一区二区三区| 国产亚洲日本欧美韩国| 欧美国产欧美亚州国产日韩mv天天看完整| 久久久久久伊人| 亚洲欧美成aⅴ人在线观看| 国产精品亚洲一区| 欧美国产先锋| 欧美在线影院| 午夜精品影院| 99精品欧美| 91久久精品日日躁夜夜躁欧美| 亚洲免费影院| 一区二区三区欧美在线观看| 精久久久久久久久久久| 国产精品热久久久久夜色精品三区| 久久露脸国产精品| 午夜亚洲性色福利视频| 亚洲视屏一区| 亚洲图片欧洲图片av| 亚洲黄色性网站| 亚洲欧洲在线观看| 亚洲欧洲一区二区三区| 欧美激情欧美激情在线五月| 久久久久九九视频| 久久久久久久一区二区三区| 久久爱91午夜羞羞| 久久久999国产| 美国十次成人| 亚洲动漫精品| 亚洲天堂免费观看| 午夜精品一区二区三区四区| 亚洲欧美日韩综合| 久久久久久久999精品视频| 久久久久久色| 欧美午夜精品理论片a级大开眼界 欧美午夜精品理论片a级按摩 | 亚洲黄一区二区三区| 亚洲大片免费看| 亚洲图片你懂的| 欧美一级免费视频| 久久亚洲二区| 欧美日韩一区二区在线观看| 国产精品美女999| 在线国产精品一区| 亚洲欧美精品| 欧美成人免费在线视频| 亚洲精品老司机| 一区二区电影免费观看| 久久久国产成人精品| 欧美日韩精品| 亚洲成色最大综合在线| 亚洲欧美日韩在线观看a三区| 久久久www成人免费无遮挡大片| 久久永久免费| 午夜精品久久一牛影视| 欧美日韩亚洲激情| 亚洲精品国产精品国自产观看浪潮| 亚洲综合日韩在线| 日韩视频在线免费观看| 美腿丝袜亚洲色图| 亚洲成人自拍视频| 久热精品视频在线观看一区| 亚洲女性裸体视频| 国产精品日韩精品欧美精品| 亚洲视频一区二区| 一区二区日韩免费看| 欧美日韩国产成人在线免费| 亚洲精品乱码久久久久久蜜桃麻豆| 久久嫩草精品久久久久| 久久精品亚洲一区| 亚洲第一中文字幕| 亚洲精品一区二| 欧美日韩高清区| 欧美在线视频网站| 久久婷婷国产综合精品青草| 在线成人小视频| 亚洲欧洲三级| 国产免费观看久久| 久久久五月天| 欧美精品91| 久久婷婷综合激情| 欧美性事在线| 老司机精品视频网站| 欧美人妖在线观看| 欧美综合二区| 欧美日韩成人综合| 老司机成人网| 国产欧美日韩视频一区二区三区 | 一区二区三区 在线观看视频 | 欧美日韩二区三区| 欧美99在线视频观看| 欧美少妇一区二区| 欧美大片网址| 娇妻被交换粗又大又硬视频欧美| 亚洲国产成人精品久久| 国产一区二区高清| 亚洲欧美在线另类| 亚洲尤物精选| 欧美日韩亚洲高清一区二区| 免费日韩av| 在线免费一区三区| 久久精品亚洲乱码伦伦中文| 亚洲欧美日韩久久精品| 欧美系列一区| 亚洲一区免费网站| 亚洲欧美999| 国产亚洲欧美日韩精品| 久久福利一区| 欧美成年人视频网站| 亚洲电影中文字幕| 欧美国产一区二区| 亚洲麻豆视频| 亚洲欧美日韩中文播放| 国产精品一区免费在线观看| 亚洲欧美国产不卡| 免费看成人av| 一本久道久久综合婷婷鲸鱼| 国产精品久久久久久久久久久久| 亚洲午夜小视频| 久久综合给合久久狠狠色 | 亚洲黄色影片| 欧美一区免费视频| 亚洲国产日韩欧美在线99| 欧美高清免费| 欧美中文字幕视频| 亚洲六月丁香色婷婷综合久久| 亚洲欧美一区二区三区在线| 一区精品久久| 国产日韩欧美在线看| 欧美日韩国产另类不卡| 久久精选视频| 欧美呦呦网站| 亚洲一二三四久久| 亚洲精品欧美精品| 亚洲高清视频的网址| 久久精品国产77777蜜臀| 在线性视频日韩欧美| 亚洲国产婷婷香蕉久久久久久99 | 欧美激情一区二区三区全黄 | 亚洲第一偷拍| 欧美高清视频一区二区三区在线观看| 午夜一区不卡| 亚洲欧美日韩一区二区| 在线亚洲高清视频| 91久久视频| 一区二区av在线| 99精品视频一区二区三区| 欧美专区在线| 久久中文字幕一区| 麻豆久久婷婷| 欧美喷水视频| 国产精品视频一二| 国户精品久久久久久久久久久不卡 | 久久性色av| 欧美精品在线免费| 国产精品一区二区三区成人| 国产精品嫩草久久久久| 国内精品一区二区三区|