首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

經驗分享:從 C 邁向 C++(三)——函數模板與運算子多載

     編輯:C++ 入門

C++ 技術雖然盛行,許多 C 開發者都渴望在短時間內掌握它。市面上介紹 C++ 的書籍不少,但真正能幫助初學者「輕鬆跨越」的資源卻不多。本文針對有一定 C 語言基礎(甚至熟練使用指標)的讀者,透過實際代碼示例,帶領大家從淺入深理解 C++ 核心特性——這裡以 Borland C++ 3.1 為示範環境。

4. 函數模板

前文討論的函數多載雖能實現求和運算,但顯得不夠優雅。若需支援 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;
}

函數模板雖類似巨集,但具備型別檢查,更安全。模板也可應用於類別中,進一步增強泛型程式設計能力。

5. 運算子多載

前面為 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),賦予自然語義。以下說明常見運算子多載形式:

1) 單目運算子多載

設 @ 為單目運算子,@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

2) 雙目運算子多載

設 @ 為雙目運算子,x @ y 解釋為 operator@(x, y)。如前所述 complex operator+(complex, complex) 即屬此類。

3) new / delete 多載

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++ 的鴻溝。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved