C 無原生類/繼承/多態,但可用 **結構體 + 函數指針 + 手動 VTable** 模擬。
typedef struct Person Person;
typedef void (*DisplayFn)(Person*);
typedef void (*WriteFn)(Person*, const char*);
typedef void (*DeleteFn)(Person*);
struct Person {
void *derived; // 指向派生對象 (多態關鍵)
char *first_name;
char *last_name;
DisplayFn display;
WriteFn write;
DeleteFn del;
};
Person* new_Person(const char* fn, const char* ln) {
Person *p = malloc(sizeof(Person));
p->derived = p; // 基類指向自己
p->first_name = strdup(fn);
p->last_name = strdup(ln);
p->display = Person_Display;
p->write = Person_Write;
p->del = delete_Person;
return p;
}
void Person_Display(Person *p) { printf("Person: %s %s\n", p->first_name, p->last_name); }
void Person_Write(Person *p, const char* f) { /* ... */ }
void delete_Person(Person *p) { free(p->first_name); free(p->last_name); free(p); }
typedef struct Employee Employee;
struct Employee {
Person *base; // 指向基類部分
char *dept;
char *company;
int salary;
};
Person* new_Employee(const char* fn, const char* ln,
const char* dept, const char* comp, int sal) {
Person *p = new_Person(fn, ln); // 先建基類
Employee *e = malloc(sizeof(Employee));
e->base = p;
e->dept = strdup(dept);
e->company = strdup(comp);
e->salary = sal;
p->derived = e; // 基類 derived 指向派生對象
// 覆寫 VTable (多態核心)
p->display = Employee_Display;
p->write = Employee_Write;
p->del = delete_Employee; // 析構鏈
return p;
}
void Employee_Display(Person *p) {
Employee *e = (Employee*)p->derived;
printf("Employee: %s %s, Dept: %s, Salary: %d\n",
e->base->first_name, e->base->last_name, e->dept, e->salary);
}
void delete_Employee(Person *p) {
Employee *e = (Employee*)p->derived;
free(e->dept); free(e->company);
delete_Person(p); // 呼叫基類析構
}
int main() {
Person *p1 = new_Person("Anjali", "Jaiswal");
Person *p2 = new_Employee("Gauri", "Jaiswal", "HR", "TCS", 40000);
p1->display(p1); // Person: Anjali Jaiswal
p2->display(p2); // Employee: Gauri Jaiswal, Dept: HR, Salary: 40000
p1->del(p1);
p2->del(p2); // 自動呼叫 delete_Employee -> delete_Person
return 0;
}
display, write, del)。derived 指向派生,派生 base 指向基類。Person* (基類指針),透過 derived 存取派生資料。_Generic + 組合而非繼承組合 (Composition) 通常比模擬繼承更符合 C 風格,避免複雜指針網。