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;

总结

差异原因

  1. C++原生继承:通过class Derived : public Base语法直接支持,编译器处理内存布局和虚函数表

  2. C语言模拟:通过结构体组合实现,将基类结构体作为派生类的第一个成员

  3. 类型系统:C语言缺乏类型安全继承,需要手动类型转换

模拟特点

  1. 结构体组合:通过将基类结构体作为第一个成员实现内存布局继承

  2. 类型转换:通过强制类型转换在基类和派生类之间转换

  3. 方法继承:通过函数指针和宏定义实现方法继承和重写

  4. 多态模拟:通过基类指针操作不同派生类对象实现多态

  5. 内存安全:需要手动管理类型转换的安全性

这种继承模拟方式在嵌入式系统中被广泛采用,它既保持了C语言的性能和资源效率,又获得了面向对象的代码组织和复用好处,是资源受限环境下实现复杂软件架构的重要手段。

posted @ 2025-11-08 15:37  ycfenxi  阅读(6)  评论(0)    收藏  举报