继承
核心技巧:基类作为子类第一个字段。
C 标准保证:结构体首字段的地址 == 结构体本身的地址,所以 (Vehicle*)&car 转换是安全的。
基类
typedef struct {
char brand[32];
int year;
} Vehicle;
void Vehicle_init(Vehicle* v, const char* brand, int year) {
strncpy(v->brand, brand, sizeof(v->brand) - 1);
v->brand[sizeof(v->brand) - 1] = '\0';
v->year = year;
}
void Vehicle_print(const Vehicle* v) {
printf("Vehicle{brand=%s, year=%d}", v->brand, v->year);
}
子类 Car(继承 Vehicle)
typedef struct {
Vehicle base; /* 继承 —— 首字段就是基类 */
int doors; /* 扩展字段 */
} Car;
void Car_init(Car* c, const char* brand, int year, int doors) {
Vehicle_init(&c->base, brand, year); // 先初始化"父类部分"
c->doors = doors; // 再初始化自己
}
void Car_print(const Car* c) {
printf("Car{brand=%s, year=%d, doors=%d}",
c->base.brand, c->base.year, c->doors);
}
子类 Bike(继承 Vehicle)
typedef struct {
Vehicle base;
int has_basket;
} Bike;
void Bike_init(Bike* b, const char* brand, int year, int has_basket) {
Vehicle_init(&b->base, brand, year);
b->has_basket = has_basket;
}
向上转型演示
int main(void) {
Car car;
Bike bike;
Car_init(&car, "Toyota", 2020, 4);
Bike_init(&bike, "Giant", 2023, 1);
/* 向上转型:子类指针 → 基类指针(安全) */
Vehicle* v1 = (Vehicle*)&car;
Vehicle* v2 = (Vehicle*)&bike;
Vehicle_print(v1); // 输出基类共有的信息
Vehicle_print(v2);
return 0;
}