typename與class都可以用作模板形參定義的關鍵字,兩者無異~~
可是,typename的用途並非僅限於此,如下面的代碼:
在上述代碼中,iter的類型是C::const_iterator,實際的類型取決於C的類型。const_iterator 同時也是C內部的typedef 類型名。 但是,在此處,編譯器的行為不會是你預期的。
為了說明這個問題,定義兩個概念,一個是從屬名稱,一個是非從屬名稱,在上述代碼中,iter 是依賴於模板參數C的,因此被稱為
從屬名稱;同理,value是內置類型,不依賴於任何模板參數,因此被稱為 非從屬名稱。
C++編譯器在面對從屬名稱時,如果此時該從屬名稱又嵌套了其他類型,如此處的 iter就是C::const_iterator類型,這裡的
C::const_iterator 稱為嵌套從屬類型(嵌套於C類型,從屬於模板參數C)。編譯器在看到這樣的代碼時,難免會暈頭轉向,因為它
不知道const_iterator 是C內部定義的類型,還是C內部的成員變量。因此,編譯器一致約定說,對於這樣的不負責任的輸入,編譯器
一致將其認為 “這不是個類型”!!顯然這就需要在代碼中明確地告訴它,這是個類型,就這樣只需要 在 C::const_iterator 前面加上關鍵字 typename 即可。
這就是必須用到typename的地方。告訴編譯器,明確代碼的含義,如果覺得很難記住,記住下面這一個例子就可以了:
template
void f( const C & container , typename C::iterator iter); 第一個參數不需要typename,因為它並沒有設計嵌套從屬類型,它只是個從屬類型(因為與C相關), 後面的typename是必須的。
但是,這裡似乎有一些惱人的情況,前面提到說,在嵌套從屬類型之前,你需要明確的告訴編譯器,你需要的是個類型,可是有些
時候,又不能這麼做。
比如下面的情況:
1 在類定義的基類列表中出現的嵌套從屬類型之前,不能寫typename。
2 在成員初值列表中,不能使用typename。
例如下面的例子:
總之:
在template聲明時,class與typename是等價的。
typename則用在嵌套從屬類型定義時,除了在成員初值列以及基類列表中。