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

用 C 語言實現面向物件程式設計(三):繼承機制與虛函式表映射

     編輯:關於C

繼承實現:巨集模擬

透過巨集套件 OOSM 模擬類別宣告與繼承關係:

標頭檔:csqua.h —— Square 類別繼承 Rectangle

#ifndef __CSQUA_H__
#define __CSQUA_H__

#include "crect.h"

class(csqua) {
    extends(crect);   /* 繼承自 crect */
};

#endif

class、extends 為巨集,展開後建立結構體並內嵌父類別結構體作為第一個成員,實現記憶體佈局相容。

實作檔:csqua.c —— 覆寫虛函式


#include "csqua.h"

static double peri(void *this)
{
    return 4 * ((crect *)this)->width;          // 正方形周長 = 4 * 邊長
}

static double area(void *this)
{
    return ((crect *)this)->width * ((crect *)this)->width;  // 面積 = 邊長²
}

constructor(csqua)
{
    mapping(crect.imeas.peri, peri);   // 將虛函式指標指向自已實作
    mapping(crect.imeas.area, area);
}

destructor(csqua)
{
    return 1;   // 回傳 1 表示釋放記憶體
}

關鍵技術點

  1. 繼承即結構體內嵌:csqua 結構體第一個成員為 crect,指標轉換 (crect*)this 安全且零成本。
  2. 虛函式表手動映射:父類別定義介面結構體 imeas 包含函式指標;子類別建構子中用 mapping 巨集將指標指向自已實作。
  3. this 指標顯式傳遞:C 無隱含 this,所有成員函式第一參數為 void*,呼叫時手動傳遞物件指標。
  4. 建構子/解構子命名慣例:constructor(csqua)、destructor(csqua) 由巨集展開為具體函式名。

完整物件模型圖解

crect 結構體:
+------------------+
| width            |
| height           |
| imeas (vtable)   | → { peri_func, area_func }
+------------------+

csqua 結構體 (繼承):
+------------------+
| crect (父類別)   |  ← 記憶體起始位址相同
|   width          |
|   height         |
|   imeas          | → 被建構子覆寫指向 csqua 實作
+------------------+

侷限性與現代替代方案

  • 無存取控制:C 無 private/protected/public,靠命名慣例(_ 前綴)與紀律約束。
  • this 指標不可隱藏:呼叫語法 obj->method(obj, ...) 顯得冗長。
  • 多重繼承極其複雜:需手動調整指標偏移,極易出錯。
  • 現代替代:C++ 原生支援;C 專案若需 OOP,可考慮 GObject (GLib) 或自行實現輕量級物件系統。

系列總結

本系列展示:

  1. 封裝:結構體 + 函式指標模擬方法。
  2. 多型:虛函式表手動映射。
  3. 繼承:結構體內嵌 + 建構子鏈。

證明面向物件是設計思維,非語言專利。C 語言雖無語法糖,但以紀律與巨集可實現核心機制,深入理解有助於掌握 C++ 底層模型。

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