c++11 中的注意事項
1. C++11標準中讓類的解構函式預設也是noexcept(true)的。 但如果顯式地為解構函式指定了noexcept,或者類的基類或成員有noexcept(false)的解構函式,解構函式就不會再保持預設值。
2. 初始化成員變數:
c++98中,支援在類宣告中使用等號“=”進行初始化,但要求必須為靜態成員常量,而且也只能是整形或列舉型別才能初始化。
而在c++11中,允許使用等號或花括號進行非靜態成員變數的初始化,比如:
struct init{ int a = 1; double b {1.2}; }
上述程式碼中,給非靜態成員a和b分別賦予初值1和1.2.
若同時使用就地初始化和初始化列表兩種方式,結果是初始化列表後作用於非靜態成員,即最終所賦值的是初始化列表中的值。
3. 擴充套件的friend語法:
class Poly; typedef Poly P; class LiLei { friend class Poly; // c++98通過,c++11通過 }; class Jim { friend Poly; //c++98失敗,c++11通過 }; class HanMeiMei { friend P; //c++98失敗,c++11通過 };
c++11在宣告一個類為另一個類友元時,不再需要使用class關鍵字,或者使用別名。
這樣可以為類模板宣告友元:
class P; template <typename T> classPeople { friend T; }; People<P> PP; //型別P在這裡是People型別的友元 People<int> Pi; //對於int型別模板引數,友元宣告被忽略
4. c++11中阻止一個函式在派生類中被過載,使用final:
class Object { virtual void fun() = 0; }; class Base: public Object { void fun() final; }; class Derived: public Base { void fun(); //無法通過編譯 };
在類Base中將函式fun()宣告為final,那麼派生於Base的Derived類則不能過載fun()。
若在派生類中在虛擬函式宣告時使用override,表明該函式必須過載其基類中能的同名函式:
class Base { virtual void Turing() = 0; virtual void Dijkstra() = 0; virtual void VNeumann(int g) = 0; void print(); }; class Derived: public Base { void Turing() override; void Dikjstra() override; //無法通過編譯,拼寫錯誤 void VNeumann(double g); //無法通過編譯,引數不一致 void print() override; //無法通過編譯,非虛擬函式過載 };
若沒有override修飾符,則Derived則會通過編譯,但並沒有實現想要過載的功能。
5. 模板函式的預設模板引數
在c++98中函式模板不能有預設引數,而在c++11中則可以有:
void DefParm(int m = 3) {} //c++98通過編譯,c++11通過編譯 template <typename T = int> class DefClass {}; //c++98通過編譯,c++11通過編譯 template <typename T = int> void DefTempParm() {}; //c++98編譯失敗,c++11通過編譯
對於類模板來說,預設模板引數宣告指定預設值時,需要按照從右往左的規則進行指定,而對於函式模板則不是必須的。
template <typename T1, typename T2 = int> class DefClass1; template <typename T1 = int, typename T2> class DefClass2; //無法通過編譯 template <typename T, int i = 0> class DefClass3; template <int i = 0, typename T> class DefClass4; //無法通過編譯 template <typename T1 = int, typename = T2> void DefFunc1(T1 a, T2 b); template <int i = 0, typename T> void DefFunc2(T a);
6. 外部模板
編譯時,對於原始碼中出現的每一處模板例項化,編譯器都需要去做例項化的通過;而在連結時,連結器還需要移除重複的例項化程式碼。解決該問題的方法是使用外部模板。c++98中已有的一個特性是顯式例項化:
template <typename T> void fun(T) {} 宣告: template void fun<int>(int);
在c++11中,外部模板的宣告為:
extern template void fun<int>(int);
7. 區域性和匿名型別作為模板實參
template <tyypename T> class X {}; template <typename T> void TempFun(T t) {} struct A {} a; struct { int i; } b; //匿名型別變數 typedef struct { int i; } B; //匿名型別 void Fun() { struct C {} c; //區域性型別 X<A> x1; //c++98通過,c++11通過 X<B> x2; //c++98不通過,c++11通過 X<C> x3; //c++98不通過,c++11通過 TempFun(a); //c++98通過,c++11通過 TempFun(b); //c++98不通過,c++11通過 TempFun(c); //c++98不通過,c++11通過 }