從 C 到 C++


C 語言當中可以用的語法, 在 C++ 當中幾乎都可以使用, 而且幾乎都保留有原來的意義. C++ 語言當中許多新的語法也可以用 C 程式來模擬, 事實上早期的 C++ 編譯器其實只不過是將 C++ 程式翻譯成 C 程式原始碼的前置處理器而已. 因此將 C 程式語言 先學好, 對於學 C++ 語言將有莫大的幫助.

本章介紹 C++ 語言對 C 語言所作的擴充中, 與物件導向觀念較不相關的部分.

  1. 多用 // 形式的註解, 少用 /* ... */ 形式的註解. (比較不會不小心出現重疊註解究竟應該如何理解的困擾.)
  2. #include <iostream.h> 取代 #include <stdio.h>, 以 cout << ... << ... 取代 printf("...", ...)cin >> ... >> ... 取代 scanf("...", ...)
  3. new 取代 malloc(), 以 delete 取代 free(). 例:
                int * p;                    int * p;
                p = malloc(sizeof(int));    p = new int;
                free(p);                    delete p;
                p = malloc(sizeof(int)*12);     p = new int[12];
                free(p);                    delete [] p;
        
    

    (不必 #include <malloc.h>或其他 header 檔了.)
  4. 多用 const, 少用沒有參數的 #define.
  5. 多用 bool 型別.
  6. 真的需要強迫型別轉換時, 最好使用 double(...) (數字型別之間的轉換); 其次可用 static_cast<double>(...) (相關指標型別之間的轉換); 或 const_cast<double>(...) (破壞常數承諾). 不要使用 (double) (...) (舊的寫法).
  7. 以 inline function 取代有參數的 #define
  8. class ... { ... }; 取代 typedef struct { ... } ...; 類別宣告: class date;
  9. 變數宣告/定義可以不必在函數 (或區段) 的開始, 可以和程式的敘述穿插混雜, 甚至出現在 if, for, while, do 的條件部分 (scope 當然就比較小了). 盡量在要使用變數時才宣告.
  10. 不要用 NULL; 直接用 0 與指標比較
  11. 把函數當做參數傳遞時, 實際參數的 & 與使用時的 * 都可有可無.
  12. 常數 (const) 內定為 internal linkage, 與 C 不同!
  13. 如何使用既有的 C 副程式庫? 用 extern "C" { ... } 把 C 的宣告與 include 包起來, 讓 C++ compiler 知道這裡宣告的函數與變數是用 C compiler 產生的. (其實要使用標準的 C 所內附的標頭檔不必這麼做.)
  14. Default Parameters (內定參數)
    1. 宣告具有內定參數的函數時, 所有具有內定值的參數都要靠在最右邊.
    2. 呼叫具有內定參數的函數時, 所有省略掉的參數都要靠在最右邊.
    3. 定義時 "= ..." 可以省略.
    4. 作業: 寫一個函數, 印出 m 的 n 進位表示法. 如果沒有說 n 是多少, 就印 16 進位.
  15. Inline Functions
    1. inline 函數效果和具有參數的 #define 一樣, 而且不會有奇怪的副作用. 它省去副程式呼叫的繁複步驟, 但每次呼叫都會產生一份程式碼. 只適合用在短小的副程式.
    2. inline 函數不可能是 extern 函數. 如果要讓大家分享, 它的定義必須連著宣告, 也放在 header 檔裡.
    3. 作業: 將 complex.c 中的 print_complex 函數改為 inline 函數. 主程式與修改後的 complex.cc 必須分開編譯.
  16. Function and Operator Overloading (函數與運算子重載)
    1. 不同的函數可以有相同的名字, 只要他們的 signature 不一樣就可以了. 所以 complex.c 當中的 complex_add 即使將名字改為 add, 也不必怕會和處理其他型別數字的 add 衝突.
    2. C 語言原有的內建運算子也可以重載, 例如:
                      class complex { double re, im; };
                      complex operator +(complex a, complex b)
                      {
                          complex c;
                          c.re = a.re + b.re;
                          c.im = a.im + b.im;
                          return c;
                      }
              
      

      把 "operator +" 想成一個完整的單元, 就像是一般的函數名稱一樣. 假設有 complex x,y,z; 則呼叫時可以用 z = operator +(x, y);z = x + y;