C++ 技術雖然盛行,許多 C 開發者都渴望在短時間內掌握它。市面上介紹 C++ 的書籍不少,但真正能幫助初學者「輕鬆跨越」的資源卻不多。本文針對有一定 C 語言基礎(甚至熟練使用指標)的讀者,透過實際代碼示例,帶領大家從淺入深理解 C++ 核心特性——這裡以 Borland C++ 3.1 為示範環境。
前文討論的函數多載雖能實現求和運算,但顯得不夠優雅。若需支援 char 等新類型,仍得重寫同樣邏輯的函數:
char Add(char a, char b) {
return a + b;
}
這類重複勞動讓人懷念巨集,但 C++ 提供了更先進的解決方案——模板:
template <class TYPE>
TYPE Add(TYPE a, TYPE b) {
return a + b;
}
TYPE 作為模板參數代表資料類型。編譯器會根據實際調用的類型自動生成對應函數:
int i = Add(1, 2); // 生成 int Add(int, int)
float f = Add(1.0, 2.0); // 生成 float Add(float, float)
若嘗試混合類型調用 Add('A', 0.0l),編譯器會報錯,因為無法匹配 Add(char, double)。
函數模板可涵蓋所有基本類型的 Add,但遇到自訂類型(如複數結構)時:
struct COMPLEX { float r; float i; };
typedef struct COMPLEX complex;
complex c1, c2;
complex c = Add(c1, c2); // 編譯器嘗試生成 complex Add(complex, complex)
由於結構體未定義 + 運算子,編譯器會報錯 Illegal structure operation。解決方法是為該類型提供專門的重載函數,這在 C++ 中稱為函數模板特化:
complex Add(complex c1, complex c2) {
complex c;
c.r = c1.r + c2.r;
c.i = c1.i + c2.i;
return c;
}
函數模板雖類似巨集,但具備型別檢查,更安全。模板也可應用於類別中,進一步增強泛型程式設計能力。
前面為 complex 寫的 Add 函數雖能工作,但非 C++ 慣用風格。我們更傾向直觀的表達:
complex c = c1 + c2; // 而非 complex c = Add(c1, c2);
C++ 允許直接對運算子 + 進行多載:
complex operator+(complex c1, complex c2) {
complex c;
c.r = c1.r + c2.r;
c.i = c1.i + c2.i;
return c;
}
當出現 c1 + c2 時,編譯器將其轉為 operator+(c1, c2),賦予自然語義。以下說明常見運算子多載形式:
設 @ 為單目運算子,@x 和 x@ 均解釋為 operator@(x)。例如 y = --x 譯為 y = operator--(x)。下例實現複數取反:
// test11.cpp
#include <iostream.h>
#include "complex.h"
complex operator-(complex c) {
c.r = -c.r;
c.i = -c.i;
return c;
}
void main() {
complex c = {1.0, 2.0};
c = -c;
cout << "c=(" << c.r << "," << c.i << "i)\n";
}
輸出:c=(-1,-2i)
++ 和 -- 可作前綴也可作後綴。後綴形式需額外 int 參數作標識:
complex operator++(complex& c, int); // 後綴 ++
complex operator--(complex& c, int); // 後綴 --
complex c;
c++; // ok
++c; // error(未定義前綴版本)
c++(0); // error
設 @ 為雙目運算子,x @ y 解釋為 operator@(x, y)。如前所述 complex operator+(complex, complex) 即屬此類。
new 和 delete 同樣可多載,典型聲明:
void* operator new(size_t size);
void operator delete(void* p);
使用 new int 時,編譯器轉為 operator new(sizeof(int))。以下示例攔截記憶體分配並改用 malloc/free:
// test12.cpp
#include <alloc.h>
#include <iostream.h>
#include "complex.h"
static void* operator new(size_t size) {
cout << size << " byte(s) allocated!\n";
return malloc(size);
}
static void operator delete(void* p) {
free(p);
cout << "memory block returned!\n";
}
void main() {
int* ip = new int(10);
complex* cp = new complex;
float* fp = new float[10];
delete[] fp;
delete cp;
delete ip;
}
輸出顯示各類型分配大小與釋放順序。聲明為 static 限制連結可見性,避免影響其他檔案。
char*)多載。! 定義為重啟機器雖合法但極差)。至此,本系列介紹完畢,望能助你輕鬆跨越 C 到 C++ 的鴻溝。