C++11--20分鍾了解C++11 (下)


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;
  }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM