先寫點題外話。本來是想在本科階段寫點兒所謂的技術部落格的,可惜最後沒有實現。究其原因,不外乎懶散而已。現在也是時候付諸行動了,寫點兒東西。隨筆之類的東西我寫了不少,部落格我想還是盡量以學習技術為主吧,偶爾穿插點我個人的感悟和廢話,呵呵。好了,閒聊到此結束,開始正題。
讀了研之後決定學學c++,因此這個系列很俗套地叫作「c++學習筆記」,今天的主要討論物件是模版。 我對c++並沒有完整的學習和研究,primer沒有通讀過,只是作為參考手冊在遇到問題或感興趣的章節時查閱一下,因此我的表述會有不嚴謹的地方,歡迎批評指正。
模版大家應該都不陌生
templateclass a{};
以上就是乙個最簡單的模版類。順便說點細節問題:第乙個細節是typename也可以換成class,並且更常用,但從含義上來說,typename更準確,因為模版引數可以為基本型別,而其不是class。typename還有另乙個作用,即告訴編譯器某個識別符號是乙個type,這在泛型和模版程式設計中很有用,因為在某些情況下,模版引數進行型別的動態繫結之前,編譯器不能在靜態編譯時期識別某個識別符號是否為乙個類,比如t::value_type,那麼,這是乙個type,還是乙個member function亦或者data member呢?t是乙個type,但除此之外,我們對其一無所知,它的內部構造是透明的,編譯器自然無法辨別,因此需要在之前加上typename關鍵字指明t::value_type為乙個type,這樣才能通過編譯。
第二個細節:將class換成struct也可以。大家可能認為struct只是一些資料的集合體,其實在c++裡,struct可以很複雜,複雜到什麼程度?在功能上與class沒有區別。當然,這是目前我所掌握的資訊,究竟有沒有本質區別,我可不敢打保票。乙個class和struct可能惟一的區別是預設訪問和繼承許可權,class的成員預設許可權是private,struct是public。我當然不是瞎說的,也查了些資料。在lippman的《inside the c++ object model(中譯本)》中和stroustrup(c++之父)的《the c++ programming language(中譯本)》中應該是這麼說的。stroustrup在p208 10.2.8節中明確寫道:乙個struct也就是乙個類,但其成員預設為公有的。事實上,在stl原始碼中,許多模版類是用struct宣告的
templatestruct iterator
;#if __cplusplus >= 201103l
_glibcxx_has_nested_type(iterator_category)
template::value>
struct __iterator_traits ;
templatestruct __iterator_traits<_iterator, true>
;templatestruct iterator_traits
: public __iterator_traits<_iterator> ;
#else
templatestruct iterator_traits
;#endif
/// partial specialization for pointer types.
templatestruct iterator_traits<_tp*>
;/// partial specialization for const pointer types.
templatestruct iterator_traits;
/*** this function is not a part of the c++ standard but is syntactic
* sugar for internal library use only.
*/templateinline typename iterator_traits<_iter>::iterator_category
__iterator_category(const _iter&)
//@}
// if _iterator has a base returns it otherwise _iterator is returned
// untouched
templatestruct _iter_base
};templatestruct _iter_base<_iterator, true>
};#if __cplusplus >= 201103l
templateusing _requireinputiter = typename
enable_if::iterator_category,
input_iterator_tag>::value>::type;
#endif
_glibcxx_end_namespace_version
} // namespace
#endif /* _stl_iterator_base_types_h */
如上,是iterator與iterator_traits的定義,在bits/stl_iterator_base_types.h檔案中,貼出來只是讓大家參考,並不是說我掌握了哈哈。
我的話是不是有點多啊,說到現在都沒說到正題。。我也不會排版,估計很難看,以後再說吧。。。
大家應該看到了,在iterator定義中,總是出現value_type一類的識別符號,為什麼呢?因為c++是靜態型別語言,在宣告和定義變數時需要明確指定變數的type,而為了實現泛型程式設計(generic programming),出現了模版(template)。
template
這樣的宣告可以使**通過編譯,但如何知道t究竟是什麼型別呢?c++提供了模版推導機制,這裡就不說了,篇幅有限。。。我所說的東西可以在侯捷的《stl原始碼剖析》裡找到。語言提供的模版推導機制有侷限性,需要進一步實現。乙個iterator如何知道自己所指向物件(包括內建基本型別)的型別和性質呢,可以在其中用value_type等字段指明。而為了支援原生指標型別,又需要再加一層封裝,就是iterator_traits。具體仍然可以參見上書,不是三兩句話就能完事的,等我再學習學習,也許會另寫一篇文章。
好了,開始下乙個討論:c++類模版的特化。
特化包括全特化( full specialization)和偏特化(partial specialization)。這兩個名詞的定義似乎不是那麼嚴格,先不管吧。
#include using namespace std;
templateclass a;
templateclass a;
template<>
class a;
int main()
以上**分別定義了乙個模板類、乙個偏特化版本、乙個全特化版本。近似來說,全特化就是全部特化,即針對所有的模板引數進行特化,偏特化就是部分特化,即針對部分模板引數進行特化。**列印的結果是2,所以呼叫的是全特化版本的類,還是近似地說,編譯器會呼叫特化程度最高的類(這句話只是根據實驗推斷的,我並沒有查閱相關理論依據)。這應該也是個比較容易理解、很自然的特性,就好像區域性變數覆蓋同名全域性變數一樣。至於函式模版,只能全特化,不能偏特化,我似乎記得在某本書上說不是因為無法實現,只是沒有必要而已,偏特化的功能可以通過函式過載實現,網上也是這麼說的~
先暫時寫到這,等有時間再修改或者再寫一篇。希望能堅持下去,歡迎一起交流學習。
要點及其他
類的載入順序 1.靜態屬性和靜態塊 按書寫順序 2.非靜態屬性和非靜態塊 按書寫順序 3.構造方法 4.被呼叫的方法 無論靜態非靜態 使android應用國際化的步驟 1.新建android xml file 2.選擇type為values 3.選擇語言碼和區域碼,語言碼設定為en或zh 區域碼設定...
日誌及其他
spring5框架自帶了通用的日誌封裝。spring5移除了log4jconfiglistener,官方建議使用log4j2,因為框架整合了log4j2.nullable 註解可以使用在方法上,屬性上和引數前,表示方法返回值可以為空,屬性值可以為空,引數值可以為空。spring5能以函式式風格建立物...
北京,年會及其他
在北京的時候,就已經看到了lisa描寫年會瞬間的部落格,半夜都把同屋給笑醒了。這個年會是難忘的,因為每個人都付出了那麼多,尤其是ark,讓我們每個人都嘆為觀止 人的潛力真是難以估量。終於上台表演了一次新疆舞,圓了兒時的乙個小夢想,今後對舞蹈依然有興趣,也有信心,呵呵,不管三七二十一,咱們今後接著跳吧...