1972:C 語言問世——C++ 的直接前身#
事件#
1972 年,Dennis Ritchie 在貝爾實驗室設計出 C 語言,用來重寫 UNIX。C 成為系統程式設計的事實標準,也是 C++ 的直接父親。
為何重要#
- C 的核心語法——
if/while/for、函式、指標、struct、前置處理器#include/#define——全部被 C++ 繼承。 - 「貼近硬體、編譯成高效機器碼」的設計目標,被 C++ 完整繼承,成為「零成本抽象(zero-overhead abstraction)」原則的起點。
- C 的缺陷也正是 C++ 誕生的原因:沒有封裝、沒有型別安全的抽象、大型專案難以維護。
理論與實用原因#
- 理論原因:BCPL → B → C 的演化,型別系統逐步補強(Ritchie 1978)。
- 實用原因:UNIX 重寫需要指標運算、位元操作與極小的執行時期開銷。
彌補了什麼缺陷#
C 彌補了組合語言「不可攜、開發緩慢」的缺陷;但它自己留下了「無封裝、無抽象、型別檢查薄弱」的缺陷——這正是 1979 年 C with Classes 要解決的問題。
程式範例#
C 語言的基本語法——指標、struct、函式:
#include <stdio.h>
struct Point { /* struct:把相關資料打包 */
int x;
int y;
};
int distance_sq(struct Point *p) { /* 指標:直接操作記憶體,高效 */
return p->x * p->x + p->y * p->y;
}
int main(void) {
struct Point p = {3, 4};
printf("%d\n", distance_sq(&p)); /* 輸出 25 */
return 0;
}
但 C 的 struct 沒有封裝——成員全公開,任何程式碼都能亂改:
p.x = -99999; /* 沒有任何機制阻止非法值 */
p.y = p.x * 3; /* 外部程式碼可以隨意繞過資料的不變式(invariant)*/
此外,所有函式都是全域的,大型專案中命名衝突風險高:
/* 檔案 a.c 與檔案 b.c 都想定義 int init(void);
連結時就會發生「重複定義」錯誤——C 沒有命名空間、
也沒有類別成員函式來隔離名字。 */
這些「無封裝、無抽象」的缺陷,正是 1979 年 C with Classes 要解決的問題。