C++11--20分鐘瞭解C++11 (下)
阿新 • • 發佈:2018-12-29
20分鐘瞭解C++11
9 override關鍵字 (虛擬函式使用)
* * 避免在派生類中意外地生成新函式 */ // C++ 03 class Dog { virtual void A(int); virtual void B() const; } class Yellowdog : public Dog { virtual void A(float); // 生成一個新函式 virtual void B(); //生成一個新函式 } // C++ 11 class Dog { virtual void A(int); virtual void B() const; void C(); } class Yellowdog : public Dog { virtual void A(float) override; // Error: no function to override virtual void B() override; // Error: no function to override void C() override; // Error: not a virtual function }
10 final (虛擬函式和類使用)
class Dog final { // 在類名後新增表示不能再從該類派生子類
...
};
class Dog {
virtual void bark() final; // 在虛擬函式後新增表示該函式不能再被覆寫
};
11 編譯器生成預設建構函式
class Dog { Dog(int age) {} }; Dog d1; // 錯誤:編譯器不會自動生成預設建構函式,因為已經有構造函數了 // C++ 11: class Dog { Dog(int age); Dog() = default; // 強制編譯器生成預設建構函式 };
12 delete 禁用某些函式
class Dog {
Dog(int age) {}
}
Dog a(2);
Dog b(3.0); // 3.0會從double型別轉成int型別
a = b; // 編譯器會生成賦值運算子
// C++ 11 手動禁用:
class Dog {
Dog(int age) {}
Dog(double ) = delete;
Dog& operator=(const Dog&) = delete;
}
13 constexpr 常量表達式
int arr[6]; //OK int A() { return 3; } int arr[A()+3]; // 編譯錯誤 // C++ 11 constexpr int A() { return 3; } // 強制計算在編譯時發生 int arr[A()+3]; // 生成一個大小為6的陣列 // 利用constexpr寫更快的程式 constexr int cubed(int x) { return x * x * x; } int y = cubed(1789); // 在編譯時計算 //cubed()函式: //1. 非常快,不消耗執行時計算 //2. 非常小,不佔據二進位制空間
14 新的字串字面值
// C++ 03:
char* a = "string";
// C++ 11:
char* a = u8"string"; // UTF-8 string.
char16_t* b = u"string"; // UTF-16 string.
char32_t* c = U"string"; // UTF-32 string.
char* d = R"string \\" // raw string.
15 lambda函式
cout << [](int x, int y){return x+y}(3,4) << endl; // Output: 7
auto f = [](int x, int y) { return x+y; };
cout << f(3,4) << endl; // Output: 7
template<typename func>
void filter(func f, vector<int> arr) {
for (auto i: arr) {
if (f(i))
cout << i << " ";
}
}
int main() {
vector<int> v = {1, 2, 3, 4, 5, 6 };
filter([](int x) {return (x>3);}, v); // Output: 4 5 6
...
filter([](int x) {return (x>2 && x<5);}, v); // Output: 3 4
int y = 4;
filter([&](int x) {return (x>y);}, v); // Output: 5 6
//注: [&] 告訴編譯器要變數捕獲
}
// Lambda函式幾乎像是一個語言的擴充套件,非常方便
// template
// for_nth_item
17 使用者自定義的字面值
// C ++在很大程度上使使用者定義的型別(類)與內建型別的行為相同.
// 使用者自定義的字面值使其又往前邁出一步
//老的C++,不知道到底表示多長?
long double height = 3.4;
// 在學校物理課的時候
height = 3.4cm;
ratio = 3.4cm / 2.1mm;
// 為什麼在程式設計時不這麼做?
// 1. 語言不支援
// 2. 單位轉換需要執行時開銷
// C++ 11:
long double operator"" _cm(long double x) { return x * 10; }
long double operator"" _m(long double x) { return x * 1000; }
long double operator"" _mm(long double x) { return x; }
int main() {
long double height = 3.4_cm;
cout << height << endl; // 34
cout << (height + 13.0_m) << endl; // 13034
cout << (130.0_mm / 13.0_m) << endl; // 0.01
}
//注: 加constexpr使單位轉換在編譯時計算
// 限制: 只能用於以下引數型別:
char const*
unsigned long long
long double
char const*, std::size_t
wchar_t const*, std::size_t
char16_t const*, std::size_t
char32_t const*, std::size_t
// 返回值可以是任何型別
// 例子:
int operator"" _hex(char const* str, size_t l) {
// 將十六進位制格式化字串str轉成int ret
return ret;
}
int operator"" _oct(char const* str, size_t l) {
// 將格式化8進位制字串str轉成 int ret
return ret;
}
int main() {
cout << "FF"_hex << endl; // 255
cout << "40"_oct << endl; // 32
}
18 可變引數模板 Variadic Template
*
* 可以接受任意個數的任意型別模板引數的模板
* 類和函式模板都可以是可變的
*/
template<typename... arg>
class BoTemplate;
BoTemplate<float> t1;
BoTemplate<int, long, double, float> t2;
BoTemplate<int, std::vector<double>> t3;
BoTemplate<> t4;
// 可變引數和非可變引數組合
template<typename T, typename... arg>
class BoTemplate;
BoTemplate<> t4; // Error
BoTemplate<int, long, double, float> t2; // OK
// 定義一個預設模板引數
template<typename T = int, typename... arg>
class BoTemplate;
19 模板別名 Template Alias
template<class T> class Dog { /* ... */ };
template<class T>
using DogVec = std::vector<T, Dog<T>>;
DogVec<int> v; // 同: std::vector<int, Dog<int>>
20 decltype
* 相當於GNU typeof
*/
const int& foo(); // 宣告一個函式foo()
decltype(foo()) x1; // 型別是const int&
struct S { double x; };
decltype(S::x) x2; // x2型別double
auto s = make_shared<S>();
decltype(s->x) x3; // x3型別double
int i;
decltype(i) x4; // x4型別int
float f;
decltype(i + f) x5; // x5型別float
// decltype對於模板泛型程式設計非常有用
template<type X, type Y>
void foo(X x, Y y) {
...
decltype(x+y) z;
...
}
// 如果返回值要使用decltype?
template<type X, type Y>
decltype(x+y) goo(X x, Y y) { // 錯誤:x 和 y 未定義
return x + y;
}
// auto和decltype組合實現具有尾隨返回型別的模板
template<type X, type Y>
auto goo(X x, Y y) -> decltype(x+y) {
return x + y;
}