問模板函數、函數模板,模板類、類模板的區別的問題? - 趙保龍 - 博客園
在C++中有好幾個這樣的術語,但是我們很多時候用的并不正確,幾乎是互相替換混淆使用。下面我想徹底辨清幾個術語,這樣就可以避免很多概念上的混淆和使用上的錯誤。 ??
? ??
? 這幾個詞是: ??
? ??
? 函數指針——指針函數 ??
? ??
? 數組指針——指針數組 ??
? ??
? 類模板——模板類 ??
? ??
? 函數模板——模板函數 ??
? ??
? 最終在使用中,我們就可以讓它們實至名歸,名正言順。 ??
? ??
? ? ??
? ??
? 1.函數指針——指針函數 ??
? ??
? 函數指針的重點是指針。表示的是一個指針,它指向的是一個函數,例子: ??
? ??
? int ? (*pf)(); ??
? ??
? 指針函數的重點是函數。表示的是一個函數,它的返回值是指針。例子: ??
? ??
? int* ? fun(); ??
? ??
? ? ??
? ??
? 2.數組指針——指針數組 ??
? ??
? 數組指針的重點是指針。表示的是一個指針,它指向的是一個數組,例子: ??
? ??
? int ? (*pa)[8]; ??
? ??
? 指針數組的重點是數組。表示的是一個數組,它包含的元素是指針。例子; ??
? ??
? int* ? ap[8]; ??
? ??
? ? ??
? ??
? 3.類模板——模板類(class ? template——template ? class) ??
? ??
? 類模板的重點是模板。表示的是一個模板,專門用于產生類的模子。例子: ??
? ??
? template ? <typename ? T> ??
? ??
? class ? Vector ??
? ??
? { ??
? ??
? ? ? ? ? ? ? … ??
? ??
? }; ??
? ??
? 使用這個Vector模板就可以產生很多的class(類),Vector<int>、Vector<char>、Vector< ? Vector<int> ? >、Vector<Shape*>……。 ??
? ??
? 模板類的重點是類。表示的是由一個模板生成而來的類。例子: ??
? ??
? 上面的Vector<int>、Vector<char>、……全是模板類。 ??
? ??
? 這兩個詞很容易混淆,我看到很多文章都將其用錯,甚至一些英文文章也是這樣。將他們區分開是很重要的,你也就可以理解為什么在定義模板的頭文件.h時,模板的成員函數實現也必須寫在頭文件.h中,而不能像普通的類(class)那樣,class的聲明(declaration)寫在.h文件中,class的定義(definition)寫在.cpp文件中。請參照Marshall ? Cline的《C++ ? FAQ ? Lite》中的[34] ? Container ? classes ? and ? templates中的[34.12] ? Why ? can't ? I ? separate ? the ? definition ? of ? my ? templates ? class ? from ? it's ? declaration ? and ? put ? it ? inside ? a ? .cpp ? file? ? URL地址是http://www.parashift.com/c++-faq-lite/containers-and-templates.html#faq-34.12 ??
? ??
? 我將幾句關鍵的段落摘錄如下,英文很好理解: ??
? ??
? In ? order ? for ? the ? compiler ? to ? generate ? the ? code, ? it ? must ? see ? both ? the ? template ? definition ? (not ? just ? declaration) ? and ? the ? specific ? types/whatever ? used ? to ? "fill ? in" ? the ? template. ? For ? example, ? if ? you're ? trying ? to ? use ? a ? Foo<int>, ? the ? compiler ? must ? see ? both ? the ? Foo ? template ? and ? the ? fact ? that ? you're ? trying ? to ? make ? a ? specific ? Foo<int>. ? ??
? ??
? Suppose ? you ? have ? a ? template ? Foo ? defined ? like ? this: ? ??
? ??
? ? template<class ? T> ??
? ? class ? Foo ? { ??
? ? public: ??
? ? ? ? Foo(); ??
? ? ? ? void ? someMethod(T ? x); ??
? ? private: ??
? ? ? ? T ? x; ??
? ? }; ? ??
? ??
? Along ? with ? similar ? definitions ? for ? the ? member ? functions: ? ??
? ??
? ? template<class ? T> ??
? ? Foo<T>::Foo() ??
? ? { ??
? ? ? ? ... ??
? ? } ??
? ? ??
? ? template<class ? T> ??
? ? void ? Foo<T>::someMethod(T ? x) ??
? ? { ??
? ? ? ? ... ??
? ? } ? ??
? ??
? Now ? suppose ? you ? have ? some ? code ? in ? file ? Bar.cpp ? that ? uses ? Foo<int>: ? ??
? ??
? ? // ? Bar.cpp ??
? ? ??
? ? void ? blah_blah_blah() ??
? ? { ??
? ? ? ? ... ??
? ? ? ? Foo<int> ? f; ??
? ? ? ? f.someMethod(5); ??
? ? ? ? ... ??
? ? } ? ??
? ??
? Clearly ? somebody ? somewhere ? is ? going ? to ? have ? to ? use ? the ? "pattern" ? for ? the ? constructor ? definition ? and ? for ? the ? someMethod() ? definition ? and ? instantiate ? those ? when ? T ? is ? actually ? int. ? But ? if ? you ? had ? put ? the ? definition ? of ? the ? constructor ? and ? someMethod() ? into ? file ? Foo.cpp, ? the ? compiler ? would ? see ? the ? template ? code ? when ? it ? compiled ? Foo.cpp ? and ? it ? would ? see ? Foo<int> ? when ? it ? compiled ? Bar.cpp, ? but ? there ? would ? never ? be ? a ? time ? when ? it ? saw ? both ? the ? template ? code ? and ? Foo<int>. ? So ? by ? rule ? above, ? it ? could ? never ? generate ? the ? code ? for ? Foo<int>::someMethod(). ? ??
? ??
? 關于一個缺省模板參數的例子: ??
? ??
? template ? <typename ? T ? = ? int> ??
? ??
? class ? Array ??
? ??
? { ??
? ??
? ? ? ? ? ? ? … ??
? ??
? }; ??
? ??
? 第一次我定義這個模板并使用它的時候,是這樣用的: ??
? ??
? Array ? books;//我認為有缺省模板參數,這就相當于Array<int> ? books ??
? ??
? 上面的用法是錯誤的,編譯不會通過,原因是Array不是一個類。正確的用法是Array<> ? books; ??
? ??
? 這里Array<>就是一個用于缺省模板參數的類模板所生成的一個具體類。 ??
? ??
? ? ??
? ??
? 4.函數模板——模板函數(function ? template——template ? function) ??
? ??
? 函數模板的重點是模板。表示的是一個模板,專門用來生產函數。例子: ??
? ??
? template ? <typename ? T> ??
? ??
? void ? fun(T ? a) ??
? ??
? { ??
? ??
? ? ? ? ? ? ? … ??
? ??
? } ??
? ??
? 在運用的時候,可以顯式(explicitly)生產模板函數,fun<int>、fun<double>、fun<Shape*>……。 ??
? ??
? 也可以在使用的過程中由編譯器進行模板參數推導,幫你隱式(implicitly)生成。 ??
? ??
? fun(6);//隱式生成fun<int> ??
? ??
? fun(8.9);//隱式生成fun<double> ??
? ??
? fun(‘a’);// ? 隱式生成fun<char> ??
? ??
? Shape* ? ps ? = ? new ? Cirlcle; ??
? ??
? fun(ps);//隱式生成fun<Shape*> ??
? ??
? ? ??
? ??
? 模板函數的重點是函數。表示的是由一個模板生成而來的函數。例子: ??
? ??
? 上面顯式(explicitly)或者隱式(implicitly)生成的fun<int>、fun<Shape*>……都是模板函數。 ??
? ??
? 關于模板本身,是一個非常龐大的主題,要把它講清楚,需要的不是一篇文章,而是一本書,幸運的是,這本書已經有了:David ? Vandevoorde, ? Nicolai ? M. ? Josuttis寫的《C++ ? Templates: ? The ? Complete ? Guide》。可惜在大陸買不到紙版,不過有一個電子版在網上流傳。 ??
? ??
? ? ??
? ??
? 模板本身的使用是很受限制的,一般來說,它們就只是一個產生類和函數的模子。除此之外,運用的領域非常少了,所以不可能有什么模板指針存在的,即指向模板的指針,這是因為在C++中,模板就是一個代碼的代碼生產工具,在最終的代碼中,根本就沒有模板本身存在,只有模板具現出來的具體類和具體函數的代碼存在。 ??
? ??
? 但是類模板(class ? template)還可以作為模板的模板參數(template ? template ? parameter)使用,在Andrei ? Alexandrescu的《Modern ? C++ ? Design》中的基于策略的設計(Policy ? based ? Design)中大量的用到。 ??
? ??
? template< ? typename ? T, ? template<typename ? U> ? class ? Y> ??
? ??
? class ? Foo ??
? ??
? { ??
? ??
? ? ? ? ? ? ? … ??
? ??
? }; ??
? ??
? ? ??
? ??
? 從文章的討論中,可以看到,名字是非常重要的,如果對名字的使用不恰當的話,會引起很多的麻煩和誤解。我們在實際的程序中各種標識符的命名也是一門學問,為了清晰易懂,有時候還是需要付出一定的代價。 ??
? ??
? 最后提醒:在本文的幾個術語中,語言的重心在后面,前面的詞是作為形容詞使用的。 ??
? ??
? 吳桐寫于2003.6.1 ??
? ??
? 最近修改2003.6.16 ??
? 這個是一個哥們在CSDN上寫的東東,呵呵 ??
? http://www.csdn.net/develop/read_article.asp?id=19075
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
