1. 程式人生 > >Typename和Class在宣告模板時的區別

Typename和Class在宣告模板時的區別

宣告template引數時,字首關鍵詞class和typename可互換。也就是說以下兩個沒有區別:

(1)template<class T>class Widget;

(2)template<typename>class Widget。

然而C++並不總是把class和typename視為等價。有時一定得使用typename。

這種時機就是:任何時候當想要在template中指涉一個巢狀從屬型別名稱,就必須在緊鄰它的前一個位置放上關鍵字typename,只有如下一個例外:不得在base class list(基類列)或member initializationlist(成員初值列)內以它作為base class修飾符。其中:template內出現的名稱如果相依於某個template引數,稱之為從屬名稱。如果從屬名稱在class內呈巢狀狀,我們稱它為巢狀從屬名稱。C::const_iterator(看下面例子)就是這樣的一個名稱。實際上它還是個巢狀從屬型別名稱,也就是個巢狀從屬名稱並且指涉某型別。看下面例子:

template <typename C>
void print2nd(const C& container)
{
 if(container.size()>=2)
 {
  C::const_iterator iter(container.begin());
  ++iter;
  int value = *iter;
  cout<<value<<endl;
 }
}

巢狀從屬名稱有可能引起解析困難。如下面的例子(將上面的改一下):

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

按照正常的理解我們應該是聲明瞭一個x的區域性變數,但是前提是我們知道C::const_iterator是個型別,但是萬一不是呢,比如C是個類並且它有一個const_iterator的靜態成員變數呢而且x又是一個全域性變數,那麼上面的就是一個相乘的動作,即C::const_iterator乘以x。引起歧義。

在我們知道C是什麼之前,沒有任何辦法可以知道C::const_iterator是否是一個型別。而當編譯器開始解析template print2nd時,尚未知C是什麼東西。C++有個規則可以解析此一歧義狀態:如果解析器在template中遭遇一個巢狀從屬名稱,它便假設這名稱不是一個型別,除非你告訴它是。所以預設情況下巢狀從屬名稱不是型別。此規則有個例外,稍後會談到。我們告訴它是隻需在C::const_iterator前加上關鍵字typename即可。

注意typename只被用來驗明巢狀從屬型別名稱;其他名稱不該有它存在。如下面的例子:

template<typename C>

void f(const C& container,typename C::iterator iter)。引數中第一個不是巢狀從屬型別名稱,所以不需要關鍵字typename,而第二個需要。

“typename必須作為巢狀從屬型別名稱的字首詞”這一規則的例外是,typename不可以出現在base classes list內的巢狀從屬型別名稱之前,也不可在member initalization list(成員初始列)中作為base class修飾符。例如:

template<typename T>
class Derived:public Base<T>::Nested     //base list中不允許"typename"
{
public:
 explicit Derived(int x)
  :Base<T>::Nested(x)               //mem init list中不允許有"typename"
 {
  typename Base<T>::Nested temp;    //這個一定要有"typename"
 }
}

最後宣告一點:以上講的在VC++ 6.0下不適用,也就是說在VC下不用typename修飾巢狀從屬型別,編譯器也不會抱怨,但是在gcc核心下就會發生抱怨。

參考文獻:《Effective C++》

相關推薦

TypenameClass宣告模板區別

宣告template引數時,字首關鍵詞class和typename可互換。也就是說以下兩個沒有區別: (1)template<class T>class Widget; (2)template<typename>class Widget。 然而C++

C++中typenameclass宣告模板區別

問題 在下面的 template declarations(模板宣告)中 class 和 typename 有什麼不同? template<class T> class Widget; // uses "class" template

定義模板typenameclass區別

在c++Template中很多地方都用到了typename與class這兩個關鍵字,而且好像可以替換,是不是這兩個關鍵字完全一樣呢? 相信學習C++的人對class這個關鍵字都非常明白,class用於定義類,在模板引入c++後,最初定義模板的方法為: temp

【C++模板】C++宣告模板能否用struct關鍵字代替class或者typename

        我們知道C++中宣告一個函式或者類的模板支援兩種關鍵字class和typename: template <class T> struct Person { public: T age; }; 或者 template <typenam

C++中typenameclass區別

type .get true 能夠 class .... ray pla 依賴 在c++Template中很多地方都用到了typename與class這兩個關鍵字,而且好像可以替換,是不是這兩個關鍵字完全一樣呢? 相信學習C++的人對class這個關鍵字都非常明白,clas

c++模板中的 typename class

在c++Template中很多地方都用到了typename與class這兩個關鍵字,而且在泛型程式設計的時候可以替換,但是 typename 和 class 並不是完全一致的。 相信學習C++的人對class這個關鍵字都非常明白,class用於定義類,在模板引入c++後,最初定義模板的方法

typenameclass區別

typename用來說明一個qualified name是一個型別。比如:  template<class C> void f(C& rc) {         Typename C::iterator i = rc.begin();         //  ...  }  編譯器不知道C

Class class物件(執行的型別資訊)

什麼是類?可以理解為。class檔案 某種意義上來說,java有兩種物件:例項物件和Class物件。每個類的執行時的型別資訊就是用Class物件表示的。它包含了與類有關的資訊。其實我們的例項物件就通過Class物件來建立的。Java使用Class物件執行其RTTI(執行時型別識別,Run-Tim

函式表示式()()函式宣告function的區別

區分函式表示式和函式宣告的區別在於function的位置,如果function不是出現在一段函式的第一個詞,那麼這是一個函式表示式,若function是第一個詞,則是一個函式宣告。函式宣告和函式表示式的區別有哪些呢?我們來看下面這一段程式碼: var a = 2; func

C++中structclass定義類的區別

C++中的struct對C中的struct進行了擴充,它已經不再只是一個包含不同資料型別的資料結構了,它已經獲取了太多的功能。struct能包含成員函式嗎? 能! struct能繼承嗎? 能!! struct能實現多型嗎? 能!!!  既然這些它都能實現,那它和clas

jquery id選擇器class選擇器的區別

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <t

HTML中id選擇器class選擇器的區別(為什麼id選擇器不能重複)

id選擇器與class選擇器的區別: 區別 1:只能在文件中使用一次與類不同,在一個 HTML 文件中,ID 選擇器會使用一次,而且僅一次。區別 2:不能使用 ID 詞列表不同於類選擇器,ID 選擇器不能結合使用,因為 ID 屬性不允許有以空格分隔的詞列表。區別 3:ID

css中id選擇器class選擇器的區別

ID選擇器: id 選擇器可以為標有特定 id 的 HTML 元素指定特定的樣式。 id 選擇器以 "#" 來定義。 下面的兩個 id 選擇器,第一個可以定義元素的顏色為紅色,第二個定義元素的顏色為綠色

for迴圈繫結事件,varlet宣告迴圈變數的區別

在理解var、let、const三者在宣告變數的區別時,遇到了一道十分有意思的題:<body> <ul> <li>第一個li</li> <li>第二個li</li> <li>第三個li&

idclass區別

xhtml 特殊符號 好的 web 沒有 定義 開頭 數字 推薦 id和class沒有本質上的區別,很多時候可以混用(XHTML不允許,但是也不會報錯)。但符合web標準的頁面必須結構良好,有語義,有可讀性,所以為了養成良好的代碼編寫習慣,建議讀者嚴格區分。同樣的i

abstract classinterface有什麽區別?

運算符 color erl 沒有 抽象類 final trac 中繼 nal   聲明方法的存在而不去實現它的類被叫做抽象類(abstract class),它用於要創建一個體現某些基本行為的類,並為該類聲明方法,但不能在該類中實現該類的情況。不能創建abstract 類的

值類型引用類型的區別,structclass區別

tro 處理 數據結構和算法 ron ever ring net string 分配 C#值類型和引用類型 1、簡單比較   值類型的變量直接存儲數據,而引用類型的變量持有的是數據的引用,數據存儲在數據堆中。   值類型(value type):byte,short,int

public clasclass區別

字節碼 public 一個 static ring rgs nbsp string clas public clas和class的區別 * 一個java源文件中可以定義多個class public class K { public static void main(St

Java中常量定義在interfaceclass區別(轉)

var tac 不能被繼承 ble -o err 模式 variable 個人愛好 最終結論:定義常量在interface和class中其實都行,關鍵是看你的設計和個人愛好。 Java中interface中定義變量默認都是"public static final"類型的,

57)函數模板普通函數的區別

變量 image info 普通 div 圖片 http clas 區別 1)函數模板不允許 自動類型轉化       --->就是 函數模板的函數是嚴格的變量類型匹配,是char就是char 不會自動給你轉化為 int 2)普通函數允許類型轉化      --