在 C 語言面向對象編程(一)裡說到繼承,這裡再詳細說一下。
C++ 中的繼承,從派生類與基類的關系來看(出於對比 C 與 C++,只說公有繼承):
派生類內部可以直接使用基類的 public 、protected 成員(包括變量和函數)使用派生類的對象,可以像訪問派生類自己的成員一樣訪問基類的成員 對於被派生類覆蓋的基類的非虛函數,在派生類中可以通過基類名和域作用符(::)來訪問當使用基類指針調用虛函數時,會調用指針指向的實際對象實現的函數,如果該對象未重載該虛函數,則沿繼承層次,逐級回溯,直到找到一個實現 上面的幾個特點,我們在 C 語言中能否全部實現呢?我覺得可以實現類似的特性,但在使用方法上會有些區別。後面我們一個一個來說,在此之前呢,先說繼承的基本實現。先看 C 語言中通過“包含”模擬實現繼承的簡單代碼框架:
struct base{ int a; }; struct derived{ struct base parent; int b; }; struct derived_2{ struct derived parent; int b; };
下面是帶成員函數的結構體:
struct base { int a; void (*func1)(struct base *_this); }; struct derived { struct base parent; int b; void (*func2)(struct derived* _this; };
下面是在 c 文件中實現的函數:
static void base_func1(struct base *_this) { printf("this is base::func1\n"); } static void derived_func2(struct derived *_this) { printf("this is derived::func2\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);
第一點,派生類內部可以直接使用基類的 public 、protected 成員(包括變量和函數)。具體到上面的例子,我們可以在 derived_func2 中訪問基類 base 的成員 a 和 func1 ,沒有任何問題,只不過是顯式通過 derived 的第一個成員 parent 來訪問:
static void derived_func2(struct derived *_this) { printf("this is derived::func2, base::a = %d\n", _this->parent.a); _this->parent.func1(&_this->parent); }
struct derived d; printf("base::a = %d\n",d.parent.a); struct derived *p = new_derived(); ((struct base *)p)->func1(p);