天天看點

了解 C++ 之 typename

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 <class t>         //可以是class或者是typename,定義模闆

void  f( const    c & container  ,   typename c::iterator iter);   //   第一個參數不需要typename,因為它并沒有設計嵌套從屬類型,它隻是個從屬類型(因為與c相關), 後面的typename是必須的。

但是,這裡似乎有一些惱人的情況,前面提到說,在嵌套從屬類型之前,你需要明确的告訴編譯器,你需要的是個類型,可是有些

時候,又不能這麼做。

比如下面的情況:

1

在類定義的基類清單中出現的嵌套從屬類型之前,不能寫typename。

2

在成員初值清單中,不能使用typename。

例如下面的例子:

總之:

在template聲明時,class與typename是等價的。

typename則用在嵌套從屬類型定義時,除了在成員初值列以及基類清單中。