国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

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

C++的template模板中class與typename關鍵字的區別分析

2020-05-23 14:02:28
字體:
來源:轉載
供稿:網友

在C++模板中,可以使用class或者typename來聲明模板參數,那么這兩個關鍵字有什么區別呢?

模板參數聲明
對于模板參數聲明,這兩個參數沒有區別,含義是一樣的。

template class Simple;template class Simple;

上面兩行都是聲明一個模板類Simple.

表明類型
假如我們有這樣一段代碼:

templatevoid add(const T &acontainer, T &sum){  T::const_iterator iter = container.begin();  for (; iter != container.end(); ++iter) {    sum += *iter;  }}

iter的類型是T::const_iterator,這個類型依賴模板參數T。把依賴模板參數的名稱稱為依賴名稱。當這個依賴名稱又在一個類中時,稱為嵌套依賴名稱。相對的,稱為非嵌套依賴名稱。

嵌套依賴名稱會導致編譯器編譯的困難,例如下面的代碼:

templatevoid add(const T &container){  T::const_iterator *x;  ...}

這看起來像聲明一個變量x,它的類型為T::const_iterator *。但是編譯器并不知道,也有可能類T中又一個static數據成員const_iterator,或者正好有一個全局變量x。這時上面的代碼就變成乘法操作。這是因為 C++編譯器在處理模板的時候,會將需要推導的數據類型暫時擱置,到運行時再確定。

當編譯器遇到一個模板中的嵌套依賴名稱時,編譯器將它作為變量對待。因此,需要顯示的告訴編譯器,這就需要使用關鍵字typename。

templatevoid add(const T &container, T &sum){  typename T::const_iterator iter = container.begin();  for (; iter != container.end(); ++iter) {    sum += *iter;  }}

因此,使用嵌套依賴的類型名稱時,都需要使用typename指定它是一種類型。

例外
嵌套依賴名稱在基類列表中,或者在成員初始化列表中時,不能使用typename。

templateclass Drived: public Base::Nested { // 基類列表,不要使用typenamepublic:  explicit Derived(int x): Base::Nested(x) { // 成員初始化列表,不要使用typename    typename Base::Nested temp;    ...  }  ...};

另外一些注意點

1、嵌套從屬名稱(nested dependent names)
假如template內出現的名稱如果依賴于某個模板參數,則稱其為從屬名稱(dependent names),如果從屬名稱在class內呈嵌套狀則稱之為嵌套從屬名稱(nested dependent names)。
例如:

templaet <typename T>void myPrint(const T& t){  t::const_iterator iter(t.begin());}

假設模板參數列表中的參數表示一個容器類型,則我們知道t::const_iterator一個依賴模板參數并且在容器內部,所以t::const_iterator是一個嵌套從屬名稱。

在我們知道t是什么之前沒有辦法可以知道t::const_iterator是否是一個類型,因為有還可能是個靜態(static)成員變量,考慮下面的例子:

template <typename T>void myPrint(const T& t){  t::const_iterator * x;}

如果const_iterator是t的靜態成員變量,則上面的t::const_iterator * x;中的*表示乘法,如果是個類型則表示聲明一個指向t::const_iterator類型的指針。
從而給編譯器造成困惑(因為我們不知道t是什么)。

C++有個規定:當解析器在模板中遇到一個嵌套從屬名稱時便假定這個名稱不是類型,除非你用關鍵字typename指定它是:

template <typename T>void myPrint(const T& t){  typename t::const_iterator * x;   //這樣便不會造成困惑了}

同理不僅在內部,在參數列表里也是:

template <typename T>void f(const T& t, typename T::const_iterator cit){   //T不是嵌套從屬名稱,而T::const_iterator是,所以要在T::const_iterator前面加上typename    //....}
2、是嵌套從屬名稱但不用加typename的兩種情況
基類列表(base list)和成員初始化列表(member initializaiton list)
 
template <typename T>class Derived: public Base<T>::Nested {         //基類列表中不允許使用typenamepublic:  explicit Derived(int x): Base<T>::Nested(int x){  //初始化列表中不允許使用typename    typename Base<T>::Nested temp;         //嵌套從屬名稱(既不在基類列表中又不在初始化列表中)前面必須要加typename  }}
 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 邯郸市| 额尔古纳市| 神农架林区| 锡林浩特市| 宣城市| 渭南市| 兴安盟| 宜都市| 文化| 吴忠市| 廊坊市| 虹口区| 江西省| 锡林浩特市| 河北省| 东源县| 乌兰察布市| 比如县| 嘉荫县| 醴陵市| 高清| 明溪县| 改则县| 辽阳市| 高青县| 新乡市| 三明市| 武平县| 施甸县| 五台县| 司法| 龙门县| 雷州市| 宜丰县| 香港| 肃南| 岳阳县| 大理市| 南开区| 堆龙德庆县| 缙云县|