亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

深入理解C++關鍵字typename的介紹

2020-02-24 14:27:19
字體:
來源:轉載
供稿:網友

在C++模板中,Type名稱和類在很多地方被使用,它們似乎是可替換的,下文是武林技術頻道小編深入理解C++關鍵字typename的介紹,希望對你學習這方面知識有幫助。

問題:在下面的 template declarations(模板聲明)中 class 和 typename 有什么不同?

?

template<class T> class Widget; // uses "class"
template<typename T> class Widget; // uses "typename"


答案:沒什么不同。在聲明一個 template type parameter(模板類型參數)的時候,class 和 typename 意味著完全相同的東西。一些程序員更喜歡在所有的時間都用 class,因為它更容易輸入。其他人(包括我本人)更喜歡 typename,因為它暗示著這個參數不必要是一個 class type(類類型)。少數開發者在任何類型都被允許的時候使用 typename,而把 class 保留給僅接受 user-defined types(用戶定義類型)的場合。但是從 C++ 的觀點看,class 和 typename 在聲明一個 template parameter(模板參數)時意味著完全相同的東西。
然而,C++ 并不總是把 class 和 typename 視為等同的東西。有時你必須使用 typename。為了理解這一點,我們不得不討論你會在一個 template(模板)中涉及到的兩種名字。
假設我們有一個函數的模板,它能取得一個 STL-compatible container(STL 兼容容器)中持有的能賦值給 ints 的對象。進一步假設這個函數只是簡單地打印它的第二個元素的值。它是一個用糊涂的方法實現的糊涂的函數,而且就像我下面寫的,它甚至不能編譯,但是請將這 些事先放在一邊——有一種方法能發現我的愚蠢:

?

?

?


template<typename C> // print 2nd element in
void print2nd(const C& container) // container;
{
// this is not valid C++!
if (container.size() >= 2) {
C::const_iterator iter(container.begin()); // get iterator to 1st element
++iter; // move iter to 2nd element
int value = *iter; // copy that element to an int
std::cout << value; // print the int
}
}


我突出了這個函數中的兩個 local variables(局部變量),iter 和 value。iter 的類型是 C::const_iterator,一個依賴于 template parameter(模板參數)C 的類型。一個 template(模板)中的依賴于一個 template parameter(模板參數)的名字被稱為 dependent names(依賴名字)。當一個 dependent names(依賴名字)嵌套在一個 class(類)的內部時,我稱它為 nested dependent name(嵌套依賴名字)。C::const_iterator 是一個 nested dependent name(嵌套依賴名字)。實際上,它是一個 nested dependent type name(嵌套依賴類型名),也就是說,一個涉及到一個 type(類型)的 nested dependent name(嵌套依賴名字)。
print2nd 中的另一個 local variable(局部變量)value 具有 int 類型。int 是一個不依賴于任何 template parameter(模板參數)的名字。這樣的名字以 non-dependent names(非依賴名字)聞名。(我想不通為什么他們不稱它為 independent names(無依賴名字)。如果,像我一樣,你發現術語 "non-dependent" 是一個令人厭惡的東西,你就和我產生了共鳴,但是 "non-dependent" 就是這類名字的術語,所以,像我一樣,轉轉眼睛放棄你的自我主張。)
nested dependent name(嵌套依賴名字)會導致解析困難。例如,假設我們更加愚蠢地以這種方法開始 print2nd:

?

?

?


template<typename C>
void print2nd(const C& container)
{
C::const_iterator * x;
...
}


這看上去好像是我們將 x 聲明為一個指向 C::const_iterator 的 local variable(局部變量)。但是它看上去如此僅僅是因為我們知道 C::const_iterator 是一個 type(類型)。但是如果 C::const_iterator 不是一個 type(類型)呢?如果 C 有一個 static data member(靜態數據成員)碰巧就叫做 const_iterator 呢?再如果 x 碰巧是一個 global variable(全局變量)的名字呢?在這種情況下,上面的代碼就不是聲明一個 local variable(局部變量),而是成為 C::const_iterator 乘以 x!當然,這聽起來有些愚蠢,但它是可能的,而編寫 C++ 解析器的人必須考慮所有可能的輸入,甚至是愚蠢的。
直到 C 成為已知之前,沒有任何辦法知道 C::const_iterator 到底是不是一個 type(類型),而當 template(模板)print2nd 被解析的時候,C 還不是已知的。C++ 有一條規則解決這個歧義:如果解析器在一個 template(模板)中遇到一個 nested dependent name(嵌套依賴名字),它假定那個名字不是一個 type(類型),除非你用其它方式告訴它。缺省情況下,nested dependent name(嵌套依賴名字)不是 types(類型)。(對于這條規則有一個例外,我待會兒告訴你。)
記住這個,再看看 print2nd 的開頭:

?

?

?


template<typename C>
void print2nd(const C& container)
{
if (container.size() >= 2) {
C::const_iterator iter(container.begin()); // this name is assumed to
... // not be a type


這為什么不是合法的 C++ 現在應該很清楚了。iter 的 declaration(聲明)僅僅在 C::const_iterator 是一個 type(類型)時才有意義,但是我們沒有告訴 C++ 它是,而 C++ 就假定它不是。要想轉變這個形勢,我們必須告訴 C++ C::const_iterator 是一個 type(類型)。我們將 typename 放在緊挨著它的前面來做到這一點:

?

?

?


template<typename C> // this is valid C++
void print2nd(const C& container)
{
if (container.size() >= 2) {
typename C::const_iterator iter(container.begin());
...
}
}


通用的規則很簡單:在你涉及到一個在 template(模板)中的 nested dependent type name(嵌套依賴類型名)的任何時候,你必須把單詞 typename 放在緊挨著它的前面。(重申一下,我待會兒要描述一個例外。)
typename 應該僅僅被用于標識 nested dependent type name(嵌套依賴類型名);其它名字不應該用它。例如,這是一個取得一個 container(容器)和這個 container(容器)中的一個 iterator(迭代器)的 function template(函數模板):

?

?

?


template<typename C> // typename allowed (as is "class")
void f(const C& container, // typename not allowed
typename C::iterator iter); // typename required


C 不是一個 nested dependent type name(嵌套依賴類型名)(它不是嵌套在依賴于一個 template parameter(模板參數)的什么東西內部的),所以在聲明 container 時它不必被 typename 前置,但是 C::iterator 是一個 nested dependent type name(嵌套依賴類型名),所以它必需被 typename 前置。
"typename must precede nested dependent type names"(“typename 必須前置于嵌套依賴類型名”)規則的例外是 typename 不必前置于在一個 list of base classes(基類列表)中的或者在一個 member initialization list(成員初始化列表)中作為一個 base classes identifier(基類標識符)的 nested dependent type name(嵌套依賴類型名)。例如:

?

?

?


template<typename T>
class Derived: public Base<T>::Nested {
// base class list: typename not
public: // allowed
explicit Derived(int x)
: Base<T>::Nested(x) // base class identifier in mem
{
// init. list: typename not allowed
typename Base<T>::Nested temp; // use of nested dependent type
... // name not in a base class list or
} // as a base class identifier in a
... // mem. init. list: typename required
};


這樣的矛盾很令人討厭,但是一旦你在經歷中獲得一點經驗,你幾乎不會在意它。
讓我們來看最后一個 typename 的例子,因為它在你看到的真實代碼中具有代表性。假設我們在寫一個取得一個 iterator(迭代器)的 function template(函數模板),而且我們要做一個 iterator(迭代器)指向的 object(對象)的局部拷貝 temp,我們可以這樣做:

?

?

?


template<typename IterT>
void workWithIterator(IterT iter)
{
typename std::iterator_traits<IterT>::value_type temp(*iter);
...
}


不要讓 std::iterator_traits<IterT>::value_type 嚇倒你。那僅僅是一個 standard traits class(標準特性類)的使用,用 C++ 的說法就是 "the type of thing pointed to by objects of type IterT"(“被類型為 IterT 的對象所指向的東西的類型”)。這個語句聲明了一個與 IterT objects 所指向的東西類型相同的 local variable(局部變量)(temp),而且用 iter 所指向的 object(對象)對 temp 進行了初始化。如果 IterT 是 vector<int>::iterator,temp 就是 int 類型。如果 IterT 是 list<string>::iterator,temp 就是 string 類型。因為 std::iterator_traits<IterT>::value_type 是一個 nested dependent type name(嵌套依賴類型名)(value_type 嵌套在 iterator_traits<IterT> 內部,而且 IterT 是一個 template parameter(模板參數)),我們必須讓它被 typename 前置。
如果你覺得讀 std::iterator_traits<IterT>::value_type 令人討厭,就想象那個與它相同的東西來代表它。如果你像大多數程序員,對多次輸入它感到恐懼,那么你就需要創建一個 typedef。對于像 value_type 這樣的 traits member names(特性成員名),一個通用的慣例是 typedef name 與 traits member name 相同,所以這樣的一個 local typedef 通常定義成這樣:

?

?

?


template<typename IterT>
void workWithIterator(IterT iter)
{
typedef typename std::iterator_traits<IterT>::value_type value_type;
value_type temp(*iter);
...
}


很多程序員最初發現 "typedef typename" 并列不太和諧,但它是涉及 nested dependent type names(嵌套依賴類型名)規則的一個合理的附帶結果。你會相當快地習慣它。你畢竟有著強大的動機。你輸入 typename std::iterator_traits<IterT>::value_type 需要多少時間?
作為結束語,我應該 提及編譯器與編譯器之間對圍繞 typename 的規則的執行情況的不同。一些編譯器接受必需 typename 時它卻缺失的代碼;一些編譯器接受不許 typename 時它卻存在的代碼;還有少數的(通常是老舊的)會拒絕 typename 出現在它必需出現的地方。這就意味著 typename 和 nested dependent type names(嵌套依賴類型名)的交互作用會導致一些輕微的可移植性問題。
Things to Remember
·在聲明 template parameters(模板參數)時,class 和 typename 是可互換的。
·用 typename 去標識 nested dependent type names(嵌套依賴類型名),在 base class lists(基類列表)中或在一個 member initialization list(成員初始化列表)中作為一個 base class identifier(基類標識符)時除外。

深入理解C++關鍵字typename的介紹,大家都知道了嗎?看完上面由武林技術頻道介紹的資料,如果你已經學會這些方法,那么趕快去操作吧!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩在线视频二区| 精品亚洲aⅴ在线观看| 亚洲免费一在线| 成人国产精品久久久久久亚洲| 久久久久久国产三级电影| 国产午夜精品美女视频明星a级| 欧美性少妇18aaaa视频| 日韩av黄色在线观看| 亚洲电影在线看| 色悠久久久久综合先锋影音下载| 日韩在线免费视频观看| 日产精品99久久久久久| 日韩黄在线观看| 亚洲精品v欧美精品v日韩精品| 国产乱人伦真实精品视频| 欧美性xxxx极品hd欧美风情| 97在线视频免费| 亚洲理论片在线观看| 亚洲成人久久久| 国产精品亚洲视频在线观看| 欧美日韩成人在线观看| 亚洲人av在线影院| 最近2019年日本中文免费字幕| 久热爱精品视频线路一| 欧美一区二区三区免费观看| 亚洲专区国产精品| 一个人www欧美| 91国产美女在线观看| 欧美性受xxxx黑人猛交| 日韩小视频在线观看| 日韩av有码在线| 久操成人在线视频| 国产精品美女午夜av| 久久这里只有精品99| 日韩视频免费在线| 欧美裸体xxxxx| 精品一区二区三区四区在线| 亚洲午夜未满十八勿入免费观看全集| 成人精品福利视频| 欧美成人精品在线播放| 国产精品私拍pans大尺度在线| 欧美一区亚洲一区| 亚洲精品乱码久久久久久金桔影视| 成人黄在线观看| 欧美另类极品videosbest最新版本| 奇米一区二区三区四区久久| 不卡伊人av在线播放| 日韩**中文字幕毛片| 日韩在线视频播放| 亚洲片av在线| 久久999免费视频| 色视频www在线播放国产成人| 日韩一级裸体免费视频| 欧美精品生活片| 亚洲欧美一区二区三区四区| 亚洲精品短视频| 欧美激情精品久久久久久久变态| 精品视频久久久| 57pao国产精品一区| 久久久人成影片一区二区三区观看| 成人黄色av网站| 欧美野外猛男的大粗鳮| 欧美日韩一区二区在线播放| 中文字幕在线国产精品| 国产精品自拍视频| 国产精品va在线播放| 亚洲免费av片| 色婷婷综合久久久久| 色综合伊人色综合网站| 岛国精品视频在线播放| 2023亚洲男人天堂| 精品中文字幕视频| 亚洲精品福利在线观看| 欧美乱妇40p| 麻豆一区二区在线观看| 欧美激情欧美狂野欧美精品| 亚洲欧洲一区二区三区久久| 国产精品va在线播放我和闺蜜| 国产精品亚洲片夜色在线| 欧美专区中文字幕| 日韩小视频在线观看| 色先锋资源久久综合5566| 亚洲精选在线观看| 国产精品扒开腿做爽爽爽男男| 97超级碰在线看视频免费在线看| 亚洲二区中文字幕| 国产999视频| 国产精品第100页| 亚洲欧美在线x视频| 亚洲欧美日韩久久久久久| 亚洲3p在线观看| 91在线播放国产| 欧美日韩激情小视频| 亚洲国产精品网站| 欧美日韩国产丝袜美女| 国产精品欧美日韩| 精品久久久999| 2020久久国产精品| 国产日韩欧美另类| 亚洲黄色在线看| 久久久久久成人| 欧美成人午夜激情| 国产欧美日韩精品丝袜高跟鞋| 欧美激情免费视频| 亚洲综合精品一区二区| 国产亚洲aⅴaaaaaa毛片| 久久夜色精品国产欧美乱| 高清欧美性猛交xxxx黑人猛交| 欧美日韩国产在线看| 欧美国产日本在线| 日韩欧亚中文在线| 国产精品久久久久久av下载红粉| 欧美大胆a视频| 国产精品久久久久一区二区| 国产精品久久久久免费a∨大胸| 国产精品美女主播| 久久av资源网站| 亚洲欧洲免费视频| 欧美午夜www高清视频| 亚洲天堂av网| 久久久久久久激情视频| 亚洲人成五月天| 日韩在线观看免费高清| 5252色成人免费视频| 日本精品一区二区三区在线| 欧美黄色三级网站| 亚洲成人a**站| 国产精品一区久久久| 上原亚衣av一区二区三区| 91免费版网站入口| 97久久久免费福利网址| 欧美激情欧美激情在线五月| 亚洲精品国产精品乱码不99按摩| 久久97精品久久久久久久不卡| 久久久久国产精品一区| 国产精品久久久久久久久久小说| 久久国产精品久久久久久| 欧美最顶级丰满的aⅴ艳星| 精品激情国产视频| 国产精品永久免费视频| 最近中文字幕2019免费| 久久综合国产精品台湾中文娱乐网| 国产精品日韩欧美| 国产日韩欧美日韩| 黄色一区二区在线| 国产香蕉一区二区三区在线视频| 日韩有码片在线观看| 国产日韩在线精品av| 日韩国产欧美精品在线| 日本高清+成人网在线观看| 3344国产精品免费看| 亚洲视频欧美视频| 91精品视频在线播放| 久久九九全国免费精品观看| 久久精品久久精品亚洲人| 91精品国产综合久久久久久蜜臀| 久久99久久亚洲国产| 羞羞色国产精品| 久久成人人人人精品欧| 亚洲精品天天看| 色综合久久中文字幕综合网小说| 亚洲第一网中文字幕| 中文字幕不卡在线视频极品| 久久香蕉精品香蕉|