C++ 公有繼承下,派生類與基類關係具備:
public、protected 成員基類名:: 域作用符存取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); // 像類實例一樣使用
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 成員存取
}
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 編譯器不支援,虛函數表機制參見上一篇文章。