C语言之封装,继承,多态

本文参考:


一、封装

封装的本质就是将数据和方法集中到一个对象中,c++或者java使用的是class来实现。c语言中可以使用struct来实现同样的功能。比如下面的程序:

struct student
{
    int age;
    char *name;
    void (*read)(char *);
};

void read_book(char *book)
{
    printf("book is :%s", book);
}

int main(void)
{
    struct student s1;
    s1.age = 10;
    s1.name = strdup("xiaoming");
    s1.read = read_book;
    
    printf("name: %s age: %d\n", s1.name, s1.age);
    s1.read("math");
    
    free(s1.name)
    return 0;
}

二、继承

继承可以让子类使用父类的资源,减少重复。父类可以是将子类的共同点抽象出来,提升代码层次。
如何使用c来实现同样的效果,首先肯定还是需要struct来构建父类和子类,同时如果要达到is a的效果,从内存空间来看,也就意味着父类占据了子类内存地址的最开始位置。所以,我们可以按照下面的方式来构造继承。

struct parent
{
    void (*func1)(void);
};

struct child
{
    struct parent pt;
    void (*func2)(void);
};

void test(struct parent *p)
{
    p->func1();
}

int main()
{
    struct child cd;
    test((struct parent *)&cd);
}

三、多态

多态就是在程序运行时,父类指针可以根据具体的子类对象来执行不同的函数行为。c++中一般通过虚函数来实现。c实现多态主要是通过结构体和函数指针。

#include <stdio.h>  

// 定义基类  
struct Shape
{  
    void (*draw)(struct Shape*);  
};

// 定义派生类  
struct Circle
{  
    struct Shape shape;  
    int radius;  
};

struct Rectangle
{  
    struct Shape shape;  
    int width;  
    int height;  
};


void drawCircle(struct Shape *shape)
{  
    printf("Drawing a circle...\n");
    struct Circle *circle = (struct Circle *)shape;
    printf("Circle radius is %d\n", circle->radius);
}


void drawRectangle(struct Shape *shape)
{  
    printf("Drawing a rectangle...\n");
    struct Rectangle *rectangle = (struct Rectangle *)shape;
    printf("Rectangle width is %d\n", rectangle->width);
    printf("Rectangle height is %d\n", rectangle->height);
}

  
int main()
{  

    struct Circle circle;
    circle.shape.draw = drawCircle;
    circle.radius = 10;

    struct Rectangle rectangle;  
    rectangle.shape.draw = drawRectangle;
    rectangle.width = 10;
    rectangle.height = 20;

    struct Shape *shape;

    shape = (struct Shape *)&circle;
    shape->draw(shape);

    shape = (struct Shape *)&rectangle;
    shape->draw(shape);
  
    return 0;  
}

在Linux内核中数量最多的就是驱动程序代码,因为硬件设备是多种多样的,每种设备都会有对应的驱动程序。Linux对上层的接口都是统一和抽象的,要保证相同的接口最终能够对应到特定的硬件设备,这就需要使用多态的技巧。

include/linux/i2c.h
这个结构体定义了不少函数指针,就是实现多态的关键

struct i2c_driver {
    unsigned int class;

    /* Standard driver model interfaces */
    int (*probe)(struct i2c_client *, const struct i2c_device_id *);
    int (*remove)(struct i2c_client *);

    /* New driver model interface to aid the seamless removal of the
     * current probe()'s, more commonly unused than used second parameter.
     */
    int (*probe_new)(struct i2c_client *);

    /* driver model interfaces that don't relate to enumeration  */
    void (*shutdown)(struct i2c_client *);

    /* Alert callback, for example for the SMBus alert protocol.
     * The format and meaning of the data value depends on the protocol.
     * For the SMBus alert protocol, there is a single bit of data passed
     * as the alert response's low bit ("event flag").
     * For the SMBus Host Notify protocol, the data corresponds to the
     * 16-bit payload data reported by the slave device acting as master.
     */
    void (*alert)(struct i2c_client *, enum i2c_alert_protocol protocol,
              unsigned int data);

    /* a ioctl like command that can be used to perform specific functions
     * with the device.
     */
    int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);

    struct device_driver driver;
    const struct i2c_device_id *id_table;

    /* Device detection callback for automatic device creation */
    int (*detect)(struct i2c_client *, struct i2c_board_info *);
    const unsigned short *address_list;
    struct list_head clients;

    bool disable_i2c_core_irq_mapping;
};
drivers/i2c/i2c-slave-eeprom.c

相关推荐

  1. C语言封装继承

    2024-07-21 20:16:01       39 阅读
  2. C++入门篇----封装继承

    2024-07-21 20:16:01       62 阅读
  3. C#基础——面向对象(封装 继承 )

    2024-07-21 20:16:01       68 阅读
  4. C++中的封装继承

    2024-07-21 20:16:01       31 阅读
  5. python 面向对象(封装继承)

    2024-07-21 20:16:01       45 阅读
  6. python 的继承封装

    2024-07-21 20:16:01       40 阅读
  7. 【设计模式】封装继承、抽象、

    2024-07-21 20:16:01       39 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-21 20:16:01       145 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-21 20:16:01       159 阅读
  3. 在Django里面运行非项目文件

    2024-07-21 20:16:01       133 阅读
  4. Python语言-面向对象

    2024-07-21 20:16:01       145 阅读

热门阅读

  1. 【广告&推荐】首选积分墙:试玩星shiwanxing.com

    2024-07-21 20:16:01       30 阅读
  2. 大模型的短期记忆和长期记忆各自的使用场景

    2024-07-21 20:16:01       34 阅读
  3. 深入探索Flutter中的状态管理:使用Provider库

    2024-07-21 20:16:01       30 阅读
  4. 认识一下哈希函数

    2024-07-21 20:16:01       32 阅读
  5. 在 CentOS-Stream-9 中使用 network 代替 NetworkManager

    2024-07-21 20:16:01       27 阅读
  6. 目标检测算法

    2024-07-21 20:16:01       30 阅读
  7. 在澳大利亚留学,论文应该怎么写?

    2024-07-21 20:16:01       37 阅读
  8. 信息增益与基尼指数:决策树分裂准则的比较

    2024-07-21 20:16:01       32 阅读