C 無原生類,但可用 結構體 + 函數指針 模擬封裝、繼承、多態。關鍵是構建 虛函數表,並在基類/派生類對象間建立雙向引用。
// Person.h
typedef struct _Person Person;
// 虛函數指針類型
typedef void (*DisplayFn)(Person*);
typedef void (*WriteFn)(Person*, const char*);
typedef void (*DeleteFn)(Person*);
struct _Person {
void *derivedObj; // 指向派生對象 (多態關鍵)
char *firstName;
char *lastName;
DisplayFn display; // 虛表槽位
WriteFn writeToFile;
DeleteFn delete;
};
// 構造/析構
Person* new_Person(const char*, const char*);
void delete_Person(Person*);
// 虛函數實現
void Person_Display(Person*);
void Person_WriteToFile(Person*, const char*);
// Person.c
Person* new_Person(const char *fn, const char *ln) {
Person *p = malloc(sizeof(Person));
p->derivedObj = p; // 基類指向自己
p->firstName = strdup(fn);
p->lastName = strdup(ln);
// 綁定基類虛函數
p->display = Person_Display;
p->writeToFile = Person_WriteToFile;
p->delete = delete_Person;
return p;
}
void delete_Person(Person *p) {
free(p->firstName); free(p->lastName); free(p);
}
// Employee.h
#include "Person.h"
typedef struct _Employee Employee;
struct _Employee {
Person *baseObj; // 指向基類對象
char *department;
char *company;
int salary;
};
Person* new_Employee(const char*, const char*, const char*, const char*, int);
void delete_Employee(Person*); // 參數為基類指針,實現多態刪除
void Employee_Display(Person*);
void Employee_WriteToFile(Person*, const char*);
// Employee.c
Person* new_Employee(const char *fn, const char *ln,
const char *dept, const char *comp, int sal) {
Person *base = new_Person(fn, ln); // 調用基類構造
Employee *e = malloc(sizeof(Employee));
e->baseObj = base;
e->department = strdup(dept);
e->company = strdup(comp);
e->salary = sal;
// 關鍵:修改基類虛表指向派生實現
base->derivedObj = e;
base->display = Employee_Display;
base->writeToFile = Employee_WriteToFile;
base->delete = delete_Employee; // 析構也多態化
return base; // 返回基類指針,支持多態調用
}
void delete_Employee(Person *p) {
Employee *e = (Employee*)p->derivedObj;
free(e->department); free(e->company); free(e);
delete_Person(p); // 鏈式調用基類析構
}
Person *p1 = new_Person("Anjali", "Jaiswal");
Person *p2 = new_Employee("Gauri", "Jaiswal", "HR", "TCS", 40000);
p1->display(p1); // 調用 Person_Display
p2->display(p2); // 調用 Employee_Display (多態)
p2->delete(p2); // 正確釋放 Employee + Person 內存
| 機制 | C++ | C 手寫模擬 |
|---|---|---|
| 虛表 | 編譯器自動生成 | 結構體內函數指針數組 |
| this 指針 | 隱式傳遞 | 顯式作為第一參數傳遞 |
| 繼承 | 內存佈局拼接 | 基類含派生指針,派生含基類指針 |
| 多態調用 | vptr→vtable→函數 | 基類虛表槽位被派生構造函數覆寫 |
| 析構多態 | virtual destructor | 基類 delete 槽位指向派生析構函數 |
理解此模型有助於: