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

C/C++ 等命令式語言實現面向對象系統:虛表、接口、Mixup 與類初始化

     編輯:C++ 入門

背景

C 語言無內置 OO 支持,但可通過結構體、函數指針、手動虛表實現完整對象系統(如 GTK GObject、COM、Linux 內核 kobject)。本文系統梳理核心機制。

核心組件

1. 對象表示

struct Object { void* vtable; void* data; };

`vtable` 指向接口表(虛表),`data` 指向具體數據。單繼承時 `vtable` 即類虛表;多接口時對象含多個 `vtable` 指針或指向接口表數組。

2. 接口與虛表

struct IExample {
    struct Class* klass; // 反向指針,指向類元數據
    int (*method)(struct Object* this, int arg);
};

接口 = 函數指針集合 + 類反向指針。對象通過 `interface(obj)->method(obj, arg)` 調用。

3. 類元數據

struct Class {
    int id; size_t obj_size;
    struct Class* parent;
    void (*init)(Class*);
    void (*ctor)(Object*, void*);
    void (*dtor)(Object*);
    // ... 其他元操作
};

存儲對象大小、繼承鏈、構造/析構函數、接口表指針等運行時信息。

4. 動態類初始化

C 無編譯期元編程,類初始化必須在運行時顯式調用:

void MyClass_init() {
    declare(&MyClass, &BaseClass); // 記錄繼承、計算對象大小
    MyClass.init = MyClass_init;
    MyClass.ctor = MyClass_ctor;
    MyClass.dtor = MyClass_dtor;
    struct IExample* iface = implement(&MyClass, &IExample);
    iface->method = MyClass_method;
    mixup(&MyClass, &MyMixin); // 混入實現
    register_class(&MyClass); // 註冊到類型系統
}

主程序啟動時需手動調用所有 `XXX_init()`,極其繁瑣。解決方案:源碼分析工具自動生成初始化調用代碼。

5. 對象創建與銷毀

// 用戶分配內存
Object* obj = malloc(MyClass.obj_size);
object_init_at(obj, &MyClass); // 設置 vtable、調用 ctor

// 系統分配
Object* obj = object_new(&MyClass); // 內部 malloc + init

// 銷毀
object_destroy(obj); // 調用 dtor、free

6. 接口查找與轉換

IExample* interface(Object* obj) {
    for (itable in obj->klass->itables)
        if (itable->id == IExample_ID) return itable->vtable;
    return NULL;
}

遍歷對象類的接口表數組,找到對應接口虛表。接口表含反向指針 `klass`,可實現接口間轉換(QueryInterface 風格)。

7. 繼承與 Mixup(混入)

  • 單繼承:`declare(&Child, &Parent)` 記錄父類,對象大小 = 父大小 + 自身字段。
  • 多重繼承:C++ 複雜,此處選擇 Mixup——構造時將混入類的字段/方法直接合併到目標類,無菱形繼承問題。

簡化版對象模型(適用輕量場景)

struct Object { void (*vfunc)(void* data); void* data; };
// 構造/析構為專用函數
Object* Foo_new() { Object* o = malloc(sizeof(Object)); o->vfunc = Foo_impl; o->data = malloc(...); return o; }
void Foo_delete(Object* o) { free(o->data); free(o); }

無虛表、無接口、無繼承,僅保留「數據+行為」綁定。構造/析構函數封裝生命周期。

總結

C 實現 OO 核心三件套:對象結構(vtable+data)、類元數據、動態初始化。虛表實現多態,接口表實現多接口,Mixup 替代多重繼承。最大痛點是樣板代碼繁多,需代碼生成工具輔助。輕量場景下,簡化模型(單函數指針+專用構造/析構)更實用。

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