C语言模拟面向对象编程方法之继承 - 详解
目录
C++ 中继承
继承的介绍:
继承是面向对象编程的三大特性之一,它允许我们依据另一个类来定义一个类,使得创建和维护应用程序变得更加容易。通过继承,子类可以获得父类的属性和方法,同时可以添加自己特有的属性和方法
继承的意义:
- 提高代码复用性:子类可以直接使用父类的功能
- 提高代码扩展性:子类可以在父类基础上进行扩展
- 建立类之间的层次关系:体现现实世界中的"is-a"关系
继承类型:
- 公有继承(public):父类的公有和保护成员在子类中保持原有访问级别
- 保护继承(protected):父类的公有和保护成员在子类中变为保护级别
- 私有继承(private):父类的公有和保护成员在子类中变为私有级别
继承的用途:
- 代码重用:避免重复编写相同的代码
- 功能扩展:在现有类基础上添加新功能
- 多态基础:为运行时多态提供基础
- 层次建模:建立现实世界的层次关系模型
继承使用实例
// 基类:交通工具
class Vehicle {
protected:
std::string brand;
int speed;
int capacity;
public:
Vehicle(const std::string& b, int s, int c)
: brand(b), speed(s), capacity(c) {}
virtual void displayInfo() const {
std::cout << "Brand: " << brand
<< ", Speed: " << speed << " km/h"
<< ", Capacity: " << capacity << " people" << std::endl;
}
virtual void start() {
std::cout << brand << " is starting..." << std::endl;
}
std::string getBrand() const { return brand; }
int getSpeed() const { return speed; }
};
// 派生类:汽车
class Car : public Vehicle {
private:
int doors;
std::string fuelType;
public:
Car(const std::string& b, int s, int c, int d, const std::string& f)
: Vehicle(b, s, c), doors(d), fuelType(f) {}
void displayInfo() const override {
Vehicle::displayInfo();
std::cout << "Doors: " << doors
<< ", Fuel: " << fuelType << std::endl;
}
void honk() {
std::cout << brand << " car is honking!" << std::endl;
}
};
// 派生类:自行车
class Bicycle : public Vehicle {
private:
int gears;
bool hasBasket;
public:
Bicycle(const std::string& b, int s, int c, int g, bool basket)
: Vehicle(b, s, c), gears(g), hasBasket(basket) {}
void displayInfo() const override {
Vehicle::displayInfo();
std::cout << "Gears: " << gears
<< ", Has Basket: " << (hasBasket ? "Yes" : "No") << std::endl;
}
void ringBell() {
std::cout << brand << " bicycle is ringing bell!" << std::endl;
}
};
// 使用
Car car("Toyota", 180, 5, 4, "Gasoline");
Bicycle bike("Giant", 25, 1, 21, true);
car.start(); // 继承自Vehicle
car.honk(); // Car特有方法
car.displayInfo(); // 重写的方法
bike.start(); // 继承自Vehicle
bike.ringBell(); // Bicycle特有方法
bike.displayInfo(); // 重写的方法
C语言模拟面向对象继承
C语言没有原生继承支持,但可以通过结构体组合和函数指针来模拟继承关系。核心思想是将父类结构体作为子类结构体的第一个成员,这样可以通过内存布局实现类似继承的效果
模拟过程
// vehicle.h - 基类头文件
#ifndef VEHICLE_H
#define VEHICLE_H
typedef struct Vehicle Vehicle;
// 基类公共接口
Vehicle* vehicle_create(const char* brand, int speed, int capacity);
void vehicle_destroy(Vehicle* vehicle);
void vehicle_display_info(const Vehicle* vehicle);
void vehicle_start(Vehicle* vehicle);
const char* vehicle_get_brand(const Vehicle* vehicle);
int vehicle_get_speed(const Vehicle* vehicle);
int vehicle_get_capacity(const Vehicle* vehicle);
#endif // VEHICLE_H
// vehicle.c - 基类实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vehicle.h"
// 基类结构体定义
struct Vehicle {
char brand[50];
int speed;
int capacity;
// 虚函数表指针(模拟多态)
void (*display_info)(const Vehicle*);
void (*start)(Vehicle*);
};
// 基类方法实现
static void vehicle_display_info_impl(const Vehicle* vehicle) {
printf("Brand: %s, Speed: %d km/h, Capacity: %d people\n",
vehicle->brand, vehicle->speed, vehicle->capacity);
}
static void vehicle_start_impl(Vehicle* vehicle) {
printf("%s is starting...\n", vehicle->brand);
}
// 基类构造函数
Vehicle* vehicle_create(const char* brand, int speed, int capacity) {
Vehicle* vehicle = (Vehicle*)malloc(sizeof(Vehicle));
if (!vehicle) return NULL;
strncpy(vehicle->brand, brand, sizeof(vehicle->brand) - 1);
vehicle->brand[sizeof(vehicle->brand) - 1] = '\0';
vehicle->speed = speed;
vehicle->capacity = capacity;
// 设置默认方法实现
vehicle->display_info = vehicle_display_info_impl;
vehicle->start = vehicle_start_impl;
return vehicle;
}
void vehicle_destroy(Vehicle* vehicle) {
free(vehicle);
}
// 基类公共方法
void vehicle_display_info(const Vehicle* vehicle) {
if (vehicle && vehicle->display_info) {
vehicle->display_info(vehicle);
}
}
void vehicle_start(Vehicle* vehicle) {
if (vehicle && vehicle->start) {
vehicle->start(vehicle);
}
}
const char* vehicle_get_brand(const Vehicle* vehicle) {
return vehicle ? vehicle->brand : NULL;
}
int vehicle_get_speed(const Vehicle* vehicle) {
return vehicle ? vehicle->speed : 0;
}
int vehicle_get_capacity(const Vehicle* vehicle) {
return vehicle ? vehicle->capacity : 0;
}
// car.h - 派生类头文件
#ifndef CAR_H
#define CAR_H
#include "vehicle.h"
typedef struct Car Car;
// 派生类公共接口
Car* car_create(const char* brand, int speed, int capacity,
int doors, const char* fuel_type);
void car_destroy(Car* car);
void car_honk(Car* car);
int car_get_doors(const Car* car);
const char* car_get_fuel_type(const Car* car);
// 继承基类接口
#define car_display_info(car) vehicle_display_info((Vehicle*)(car))
#define car_start(car) vehicle_start((Vehicle*)(car))
#define car_get_brand(car) vehicle_get_brand((Vehicle*)(car))
#endif // CAR_H
// car.c - 派生类实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "car.h"
// 派生类结构体 - 第一个成员是基类
struct Car {
Vehicle base; // 基类作为第一个成员,实现内存布局继承
int doors;
char fuel_type[20];
};
// 派生类重写的方法
static void car_display_info_impl(const Vehicle* vehicle) {
const Car* car = (const Car*)vehicle; // 安全转换
printf("Brand: %s, Speed: %d km/h, Capacity: %d people\n",
car->base.brand, car->base.speed, car->base.capacity);
printf("Doors: %d, Fuel: %s\n", car->doors, car->fuel_type);
}
static void car_start_impl(Vehicle* vehicle) {
Car* car = (Car*)vehicle;
printf("%s car is starting with %s fuel...\n",
car->base.brand, car->fuel_type);
}
// 派生类构造函数
Car* car_create(const char* brand, int speed, int capacity,
int doors, const char* fuel_type) {
Car* car = (Car*)malloc(sizeof(Car));
if (!car) return NULL;
// 初始化基类部分
strncpy(car->base.brand, brand, sizeof(car->base.brand) - 1);
car->base.brand[sizeof(car->base.brand) - 1] = '\0';
car->base.speed = speed;
car->base.capacity = capacity;
// 设置派生类重写的方法
car->base.display_info = car_display_info_impl;
car->base.start = car_start_impl;
// 初始化派生类特有成员
car->doors = doors;
strncpy(car->fuel_type, fuel_type, sizeof(car->fuel_type) - 1);
car->fuel_type[sizeof(car->fuel_type) - 1] = '\0';
return car;
}
void car_destroy(Car* car) {
free(car);
}
// 派生类特有方法
void car_honk(Car* car) {
if (car) {
printf("%s car is honking!\n", car->base.brand);
}
}
int car_get_doors(const Car* car) {
return car ? car->doors : 0;
}
const char* car_get_fuel_type(const Car* car) {
return car ? car->fuel_type : NULL;
}
// bicycle.h - 另一个派生类
#ifndef BICYCLE_H
#define BICYCLE_H
#include "vehicle.h"
typedef struct Bicycle Bicycle;
Bicycle* bicycle_create(const char* brand, int speed, int capacity,
int gears, int has_basket);
void bicycle_destroy(Bicycle* bicycle);
void bicycle_ring_bell(Bicycle* bicycle);
int bicycle_get_gears(const Bicycle* bicycle);
int bicycle_has_basket(const Bicycle* bicycle);
// 继承基类接口
#define bicycle_display_info(bicycle) vehicle_display_info((Vehicle*)(bicycle))
#define bicycle_start(bicycle) vehicle_start((Vehicle*)(bicycle))
#endif // BICYCLE_H
// bicycle.c - 另一个派生类实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bicycle.h"
struct Bicycle {
Vehicle base; // 基类作为第一个成员
int gears;
int has_basket;
};
static void bicycle_display_info_impl(const Vehicle* vehicle) {
const Bicycle* bicycle = (const Bicycle*)vehicle;
printf("Brand: %s, Speed: %d km/h, Capacity: %d people\n",
bicycle->base.brand, bicycle->base.speed, bicycle->base.capacity);
printf("Gears: %d, Has Basket: %s\n",
bicycle->gears, bicycle->has_basket ? "Yes" : "No");
}
static void bicycle_start_impl(Vehicle* vehicle) {
Bicycle* bicycle = (Bicycle*)vehicle;
printf("%s bicycle is starting... pedal ready!\n", bicycle->base.brand);
}
Bicycle* bicycle_create(const char* brand, int speed, int capacity,
int gears, int has_basket) {
Bicycle* bicycle = (Bicycle*)malloc(sizeof(Bicycle));
if (!bicycle) return NULL;
// 初始化基类部分
strncpy(bicycle->base.brand, brand, sizeof(bicycle->base.brand) - 1);
bicycle->base.brand[sizeof(bicycle->base.brand) - 1] = '\0';
bicycle->base.speed = speed;
bicycle->base.capacity = capacity;
// 设置重写方法
bicycle->base.display_info = bicycle_display_info_impl;
bicycle->base.start = bicycle_start_impl;
// 初始化派生类特有成员
bicycle->gears = gears;
bicycle->has_basket = has_basket;
return bicycle;
}
void bicycle_destroy(Bicycle* bicycle) {
free(bicycle);
}
void bicycle_ring_bell(Bicycle* bicycle) {
if (bicycle) {
printf("%s bicycle is ringing bell!\n", bicycle->base.brand);
}
}
int bicycle_get_gears(const Bicycle* bicycle) {
return bicycle ? bicycle->gears : 0;
}
int bicycle_has_basket(const Bicycle* bicycle) {
return bicycle ? bicycle->has_basket : 0;
}
实际使用
// main.c - 测试继承模拟
#include <stdio.h>
#include "vehicle.h"
#include "car.h"
#include "bicycle.h"
void demonstrate_inheritance() {
printf("=== Demonstrating Inheritance in C ===\n\n");
// 创建基类对象
Vehicle* generic_vehicle = vehicle_create("Generic", 100, 4);
printf("Generic Vehicle:\n");
vehicle_display_info(generic_vehicle);
vehicle_start(generic_vehicle);
printf("\n");
// 创建派生类对象
Car* car = car_create("Toyota", 180, 5, 4, "Gasoline");
Bicycle* bicycle = bicycle_create("Giant", 25, 1, 21, 1);
// 使用继承的方法
printf("Car (using inherited methods):\n");
car_display_info(car); // 通过宏调用基类方法
car_start(car); // 重写的方法
printf("Bicycle (using inherited methods):\n");
bicycle_display_info(bicycle);
bicycle_start(bicycle);
printf("\n");
// 使用派生类特有方法
printf("Car specific methods:\n");
car_honk(car);
printf("Doors: %d, Fuel: %s\n",
car_get_doors(car), car_get_fuel_type(car));
printf("Bicycle specific methods:\n");
bicycle_ring_bell(bicycle);
printf("Gears: %d, Has Basket: %s\n",
bicycle_get_gears(bicycle),
bicycle_has_basket(bicycle) ? "Yes" : "No");
printf("\n");
// 演示多态效果 - 通过基类指针操作不同派生类对象
printf("=== Polymorphism Demo ===\n");
Vehicle* vehicles[] = {
(Vehicle*)car,
(Vehicle*)bicycle,
generic_vehicle
};
for (int i = 0; i < 3; i++) {
printf("Vehicle %d: ", i + 1);
vehicle_display_info(vehicles[i]);
vehicle_start(vehicles[i]);
}
// 清理内存
vehicle_destroy(generic_vehicle);
car_destroy(car);
bicycle_destroy(bicycle);
}
int main() {
demonstrate_inheritance();
return 0;
}
嵌入式开发中实际案例介绍
1. STM32 HAL库中的设备继承
// 通用设备基类模拟
typedef struct {
uint32_t base_address;
uint32_t clock_control;
void (*init)(void* device);
void (*deinit)(void* device);
HAL_StatusTypeDef (*start)(void* device);
HAL_StatusTypeDef (*stop)(void* device);
} Device_Base;
// UART设备派生类
typedef struct {
Device_Base base; // 继承基类
UART_InitTypeDef init; // UART特有配置
uint8_t* tx_buffer;
uint16_t tx_size;
// UART特有方法
HAL_StatusTypeDef (*transmit)(void* uart, uint8_t* data, uint16_t size);
HAL_StatusTypeDef (*receive)(void* uart, uint8_t* data, uint16_t size);
} UART_Device;
// SPI设备派生类
typedef struct {
Device_Base base; // 继承基类
SPI_InitTypeDef init; // SPI特有配置
GPIO_TypeDef* cs_port;
uint16_t cs_pin;
// SPI特有方法
HAL_StatusTypeDef (*transmit_receive)(void* spi, uint8_t* tx, uint8_t* rx, uint16_t size);
} SPI_Device;
// 使用示例
UART_Device uart1;
SPI_Device spi1;
// 统一通过基类接口操作
uart1.base.start(&uart1);
spi1.base.start(&spi1);
// 使用派生类特有接口
uart1.transmit(&uart1, data, sizeof(data));
spi1.transmit_receive(&spi1, tx_data, rx_data, size);
2. FreeRTOS中的任务继承
// 基础任务结构
typedef struct {
TaskHandle_t handle;
TaskFunction_t function;
const char* name;
uint32_t stack_depth;
UBaseType_t priority;
// 基础方法
BaseType_t (*create)(void* task);
void (*delete)(void* task);
void (*delay)(void* task, TickType_t ticks);
} BaseTask;
// 通信任务派生类
typedef struct {
BaseTask base; // 继承基础任务
QueueHandle_t queue;
SemaphoreHandle_t mutex;
// 通信特有方法
BaseType_t (*send_message)(void* task, void* msg, TickType_t timeout);
BaseType_t (*receive_message)(void* task, void* msg, TickType_t timeout);
} CommTask;
// 定时任务派生类
typedef struct {
BaseTask base; // 继承基础任务
TimerHandle_t timer;
TickType_t period;
// 定时特有方法
BaseType_t (*start_timer)(void* task);
BaseType_t (*stop_timer)(void* task);
} TimerTask;
3. LVGL中的控件继承体系
// 基础对象结构
struct _lv_obj_t {
struct _lv_obj_t * parent;
lv_ll_t child_ll;
lv_area_t coords;
lv_style_list_t style_list;
// 虚函数表
lv_signal_cb_t signal_cb;
lv_design_cb_t design_cb;
lv_event_cb_t event_cb;
};
// 按钮控件 - 继承基础对象
typedef struct {
lv_obj_t obj; // 继承基础对象
lv_btn_state_t state;
lv_style_list_t style_btn;
// 按钮特有方法
void (*set_state)(lv_obj_t* btn, lv_btn_state_t state);
lv_btn_state_t (*get_state)(const lv_obj_t* btn);
} lv_btn_t;
// 标签控件 - 继承基础对象
typedef struct {
lv_obj_t obj; // 继承基础对象
char* text;
lv_label_align_t align;
lv_style_list_t style_text;
// 标签特有方法
void (*set_text)(lv_obj_t* label, const char* text);
const char* (*get_text)(const lv_obj_t* label);
} lv_label_t;
// 使用继承关系
lv_btn_t* btn = lv_btn_create(lv_scr_act(), NULL);
lv_label_t* label = lv_label_create(btn, NULL); // 标签作为按钮的子对象
// 通过基类指针操作所有控件
lv_obj_set_size((lv_obj_t*)btn, 100, 50);
lv_obj_set_pos((lv_obj_t*)label, 10, 10);
4. Contiki-NG中的协议栈继承
// 基础网络协议结构
typedef struct network_protocol {
const char* name;
uint8_t protocol_id;
// 基础方法
void (*init)(void* protocol);
void (*input)(void* protocol, void* packet);
void (*output)(void* protocol, void* packet);
} network_protocol_t;
// IPv6协议派生类
typedef struct {
network_protocol_t base; // 继承基础协议
uip_ds6_netif_t netif;
uip_ds6_addr_t addrs;
// IPv6特有方法
void (*set_address)(void* ipv6, uip_ip6addr_t* addr);
void (*add_route)(void* ipv6, uip_ip6addr_t* network);
} ipv6_protocol_t;
// RPL路由协议派生类
typedef struct {
network_protocol_t base; // 继承基础协议
rpl_dag_t dag;
rpl_instance_t instance;
// RPL特有方法
void (*join_dag)(void* rpl, uip_ip6addr_t* dag_id);
void (*local_repair)(void* rpl);
} rpl_protocol_t;
5. Zephyr RTOS中的驱动继承模型
// 基础设备驱动结构
struct device_driver_api {
int (*init)(const struct device* dev);
int (*configure)(const struct device* dev, uint32_t config);
int (*read)(const struct device* dev, uint32_t* value);
int (*write)(const struct device* dev, uint32_t value);
};
// GPIO驱动派生API
struct gpio_driver_api {
struct device_driver_api base; // 继承基础API
// GPIO特有方法
int (*pin_configure)(const struct device* dev, gpio_pin_t pin, gpio_flags_t flags);
int (*pin_get)(const struct device* dev, gpio_pin_t pin, uint32_t* value);
int (*pin_set)(const struct device* dev, gpio_pin_t pin, uint32_t value);
};
// I2C驱动派生API
struct i2c_driver_api {
struct device_driver_api base; // 继承基础API
// I2C特有方法
int (*transfer)(const struct device* dev, struct i2c_msg* msgs, uint8_t num_msgs, uint16_t addr);
int (*configure)(const struct device* dev, uint32_t dev_config);
};
// 使用统一的设备接口访问不同驱动
const struct device* gpio_dev = device_get_binding("GPIO_0");
const struct device* i2c_dev = device_get_binding("I2C_0");
// 通过基类API操作
gpio_dev->api->init(gpio_dev);
i2c_dev->api->init(i2c_dev);
6. 嵌入式MQTT客户端继承架构
// 基础网络客户端
typedef struct {
const char* server_url;
int port;
int socket_fd;
// 基础网络方法
int (*connect)(void* client);
int (*disconnect)(void* client);
int (*send)(void* client, const void* data, size_t len);
int (*receive)(void* client, void* buffer, size_t len);
} NetworkClient;
// MQTT客户端派生类
typedef struct {
NetworkClient base; // 继承网络客户端
const char* client_id;
MQTTVersion version;
// MQTT特有方法
int (*publish)(void* mqtt, const char* topic, const void* payload, size_t len, int qos);
int (*subscribe)(void* mqtt, const char* topic, int qos);
int (*unsubscribe)(void* mqtt, const char* topic);
} MQTTClient;
// CoAP客户端派生类
typedef struct {
NetworkClient base; // 继承网络客户端
coap_uri_t server_uri;
// CoAP特有方法
int (*get)(void* coap, const char* path, void* response, size_t* response_len);
int (*put)(void* coap, const char* path, const void* data, size_t len);
int (*observe)(void* coap, const char* path, coap_response_handler_t handler);
} CoAPClient;
总结
差异原因
C++原生继承:通过class Derived : public Base语法直接支持,编译器处理内存布局和虚函数表
C语言模拟:通过结构体组合实现,将基类结构体作为派生类的第一个成员
类型系统:C语言缺乏类型安全继承,需要手动类型转换
模拟特点
结构体组合:通过将基类结构体作为第一个成员实现内存布局继承
类型转换:通过强制类型转换在基类和派生类之间转换
方法继承:通过函数指针和宏定义实现方法继承和重写
多态模拟:通过基类指针操作不同派生类对象实现多态
内存安全:需要手动管理类型转换的安全性
这种继承模拟方式在嵌入式系统中被广泛采用,它既保持了C语言的性能和资源效率,又获得了面向对象的代码组织和复用好处,是资源受限环境下实现复杂软件架构的重要手段。
浙公网安备 33010602011771号