深入理解C template的基礎知識

2021-08-07 16:27:48 字數 2878 閱讀 4941

c++現今支援兩種基本型別的模板:類模板和函式模板(也包括成員模板),

這些模板的宣告與普通類與普通函式的宣告很相似,唯一的區別就是模板宣告需要引入乙個引數化的子句,子句的格式大體如下:

template<...parameters list....>

成員函式模板不能被宣告為虛函式。因為虛函式呼叫機制的普遍實現都使用了乙個大小固定的表,每個虛函式都對應表的乙個入口。然而,成員函式模板的例項化個數,要等到整個程式都翻譯完畢才能確定,這就和表的大小發生了衝突。

相反,類模板的普通成員可以是虛函式,因為當類被例項化之後,它們的個數是固定的。

eg:

template

class dynamic

public:

virtual ~dynamic();//ok:每個dynamic之對應乙個析構函式

template

virtual void copy(t2 const&);//error:在去頂dynamic例項的時候,並不知道copy的個數,只有呼叫copy時才會真正例項化該模板成員函式

eg: extern "c++" template

void normal();//這是預設情況,上面的鏈結規範可以不寫

extern "c"  template

eg: templateclass box;

templatevoid translate(t*);

現今存在3種模板引數:

在模板宣告內部,型別引數的作用類似於typedef名稱。

所有 其他型別現今都不允許作為非型別引數使用

或許令你驚訝的是,在某些情況下,非模板引數的宣告也可以使用關鍵字typename

eg:  templatetypename t::allocator* allocator>      //非型別引數----》受限的名稱,則必須使用typename進行型別的說明

class list;

函式和陣列型別也可以被指定為非型別引數,因為它們會隱式轉換為指標型別

最後:非型別模板引數只能是右值:它們不能被取值,也不能被賦值

模板的模板引數是代表類模板的佔位符 。它的宣告和類模板的宣告很類似,但不能使用關鍵字struct和union。在它們宣告的作用域中,模板的模板引數的用法和類模板的用法很相似。

模板的模板引數的引數可以具有預設模板實參。顯然,只有在呼叫時沒有指定該引數的情況下,才會應用預設模板實參。

eg:  template< template typename a=myallocator>  class container>

class adaptation

如果我們調換了例子中模板引數的順序,也就是說我們將模板寫成template,那麼呼叫該函式的時候就必須顯式指定兩個模板實參

由於函式模板可以被過載,所以對函式模板而言,顯式提供的所有實參不足以標識每乙個函式。

模板的型別實參是一些用來指定模板型別引數的值。我們平時使用的大多數型別都可以被用作模板的型別實參,但有兩種情況例外:

通常而言,儘管其他的型別都可以用作模板實參,但前提是該型別替換模板引數之後獲得的構造必須是有效的。

非型別實參是那些替換非型別引數的值,這個值必須是以下幾種中的一種:

注意: 當「指標型別或者引用型別的引數」時,使用者定義的型別轉換和由派生類到基類的型別轉換都不會被考慮

有一些常值不能作為有效的非型別實參,這些常值包括:

模板的模板實參必須是乙個類模板,它本身具有引數,該引數必須精確匹配它「所替換的模板的模板引數」本身的引數。在匹配過程中,「模板的模板實參」的預設模板實參將不會被考慮(但是如果模板的模板引數具有預設實參,那麼模板的例項化過程是會考慮模板的模板實參的預設實參的)。

注意:從語法上講,只有關鍵字class才能被用來宣告模板的模板引數,但是這並不意味著只有用關鍵字class宣告的類模板才能作為它的替換實參。實際上,「struct模板」,「union模板」都可以作為模板的模板引數的有效實參,即:對於用關鍵字class宣告的模板型別引數,我們可以用滿足約束的任何型別作為它的替換實參

3.5 實參的等價性:當每個對應的實參值都相等時,我們就稱這兩組模板實參是等價的。對於型別實參,typedef名稱並不會對等價性產生影響,也就是說最後比較的還是typedef原本的型別。對於非型別的整型實參,進行比較的是實參的值,至於這些值是如何表達的,也不會產生影響。

注意:從函式模板產生出來的函式一定不會等於普通函式,即便這兩個函式具有相同的型別和名稱

針對類成員,我們可以引申亮點結論:

友元類的宣告不能是類定義,因此友元類通常都不會出現問題。在引入模板後,友元類宣告的唯一變化是:可以命名要給特定的類模板例項為友元

可將函式模板的例項宣告為友元:在友元函式名稱後面加一對尖括號<>,尖括號可以包含模板實參,也可以通過呼叫引數演繹出實參,如果全部實參都可以通過演繹獲得的話,尖括號可為空

注意:我們不能在友元宣告中定義乙個模板例項。

如果名稱後面沒有一對尖括號,那麼只有在下面兩種情況下是合法的:

注意: 如果我們在類模板中定義乙個友元函式,那麼將會出現乙個很有趣的現象。因為對於任何只在模板內部宣告的實體,都要等到模板被例項化之後,才會是乙個具體的實體,在此之前該實體是不存在的。類模板的友元函式也是如此。儘管這些函式是作為模板的一部分被生成的,但函式本身仍然是普通函式,而不是模板的例項

通過友元模板,可以讓模板的所有例項都成為友元

和普通友元的宣告一樣,只有在友元模板宣告的是乙個非受限的函式名稱,並且後面沒有緊跟尖括號的情況下,該友元模板宣告才能成員定義

友元模板宣告的只是基本模板和基本模板的成員。當進行這些宣告之後,與該基本模板相對應的模板區域性特化和顯式特化都會被自動看成友元。

深入理解C語言 深入理解指標

關於指標,其是c語言的重點,c語言學的好壞,其實就是指標學的好壞。其實指標並不複雜,學習指標,要正確的理解指標。指標也是一種變數,占有記憶體空間,用來儲存記憶體位址 指標就是告訴編譯器,開闢4個位元組的儲存空間 32位系統 無論是幾級指標都是一樣的 p操作記憶體 在指標宣告時,號表示所宣告的變數為指...

mysql 索引深入理解 深入理解MySql的索引

為什麼索引能提高查詢速度 先從 mysql的基本儲存結構說起 mysql的基本儲存結構是頁 記錄都存在頁裡邊 各個資料頁可以組成乙個雙向鍊錶每個資料頁中的記錄又可以組成乙個單向鍊錶 每個資料頁都會為儲存在它裡邊兒的記錄生成乙個頁目錄,在通過主鍵查詢某條記錄的時候可以在頁目錄中使用二分法快速定位到對應...

深入理解C語言 深入理解指標

關於指標,其是c語言的重點,c語言學的好壞,其實就是指標學的好壞。其實指標並不複雜,學習指標,要正確的理解指標。指標也是一種變數,占有記憶體空間,用來儲存記憶體位址 指標就是告訴編譯器,開闢4個位元組的儲存空間 32位系統 無論是幾級指標都是一樣的 p操作記憶體 在指標宣告時,號表示所宣告的變數為指...