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

C 語言面向物件程式設計(二):繼承機制深度解析與實現

     編輯:關於C

C++ 繼承特性回顧

C++ 公有繼承下,派生類與基類關係具備:

  1. 派生類內部可直接存取基類 public、protected 成員
  2. 使用派生類物件時,可像存取自身成員一樣存取基類成員
  3. 被覆蓋的非虛函數,可透過 基類名:: 域作用符存取
  4. 基類指標調用虛函數時,依實際物件類型動態綁定,未覆寫則沿繼承鏈回溯

C 語言能否實現?答案是肯定的,但使用方式有所不同。

結構體嵌套模擬繼承

純資料成員

struct base { int a; };
struct derived { struct base parent; int b; };
struct derived_2 { struct derived parent; int b; };

C 結構體無存取控制,預設皆為公有(異於 Java)。

含成員函數(函數指標)

struct base {
    int a;
    void (*func1)(struct base *_this);
};

struct derived {
    struct base parent;
    int b;
    void (*func2)(struct derived *_this);
};

關鍵點:結構體內函數指標第一個參數必須定義為自身指標(_this),調用時傳入實例指標。C 無隱含 this 指標,必須顯式傳遞才能在函數內存取其他成員。

建構函數模擬

C 僅有 malloc 分配記憶體,無自動初始化機制,需自行提供建構函數:

static void base_func1(struct base *_this) {
    printf("this is base::func1\n");
}

struct base *new_base() {
    struct base *b = malloc(sizeof(struct base));
    b->a = 0;
    b->func1 = base_func1;
    return b;
}

使用方式

struct base *b1 = new_base();
b1->func1(b1);  // 像類實例一樣使用

繼承特性的 C 語言實現

特性 1:派生類內部存取基類成員

static void derived_func2(struct derived *_this) {
    printf("this is derived::func2, base::a = %d\n", _this->parent.a);
    _this->parent.func1(&_this->parent);  // 顯式透過 parent 成員存取
}

特性 2:派生類物件存取基類成員

struct derived d;
printf("base::a = %d\n", d.parent.a);  // 必須透過 parent 成員

struct derived *p = new_derived();
((struct base *)p)->func1(p);  // 指標強制轉換可直接調用

注意:無法像 C++ 那樣直接 p->func1(p),必須透過 parent 欄位或強制轉型。

待續議題

覆蓋、重載、虛函數等進階特性將於後續文章詳細說明。虛函數可透過結構體內函數指標實現,覆蓋需避免同名函數指標造成混淆,重載受限於 C 編譯器不支援,虛函數表機制參見上一篇文章。

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