C++的template模板中class與typename症結字的差別剖析。本站提示廣大學習愛好者:(C++的template模板中class與typename症結字的差別剖析)文章只能為提供參考,不一定能成為您想要的結果。以下是C++的template模板中class與typename症結字的差別剖析正文
在C++模板中,可使用class或許typename來聲明模板參數,那末這兩個症結字有甚麼差別呢?
模板參數聲明
關於模板參數聲明,這兩個參數沒有差別,寄義是一樣的。
template class Simple; template class Simple;
下面兩行都是聲明一個模板類Simple.
注解類型
假設我們有如許一段代碼:
template void add(const T &acontainer, T &sum) { T::const_iterator iter = container.begin(); for (; iter != container.end(); ++iter) { sum += *iter; } }
iter的類型是T::const_iterator,這個類型依附模板參數T。把依附模板參數的稱號稱為依附稱號。當這個依附稱號又在一個類中時,稱為嵌套依附稱號。絕對的,稱為非嵌套依附稱號。
嵌套依附稱號會招致編譯器編譯的艱苦,例以下面的代碼:
template void add(const T &container) { T::const_iterator *x; ... }
這看起來像聲明一個變量x,它的類型為T::const_iterator *。然則編譯器其實不曉得,也有能夠類T中又一個static數據成員const_iterator,或許正好有一個全局變量x。這時候下面的代碼就釀成乘法操作。這是由於 C++編譯器在處置模板的時刻,會將須要推導的數據類型臨時棄捐,到運轉時再肯定。
當編譯器碰到一個模板中的嵌套依附稱號時,編譯器將它作為變量看待。是以,須要顯示的告知編譯器,這就須要應用症結字typename。
template void add(const T &container, T &sum) { typename T::const_iterator iter = container.begin(); for (; iter != container.end(); ++iter) { sum += *iter; } }
是以,應用嵌套依附的類型稱號時,都須要應用typename指定它是一品種型。
破例
嵌套依附稱號在基類列表中,或許在成員初始化列表中時,不克不及應用typename。
template class Drived: public Base::Nested { // 基類列表,不要應用typename public: 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的兩種情形
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 } }