1. 主页 > 小妙招

C语言实现抽象类方法调用:结构体函数指针实战

哎,各位码友!你们有没有想过,C语言这个老古董居然也能玩面向对象?别急着摇头,今天咱们就来整点刺激的——??用结构体函数指针模拟抽象类方法调用??!是不是听着有点玄乎?别慌,我保证用大白话给你讲明白!(内心OS:这玩意儿其实比指针数组简单多了...)


??"C语言不是面向过程的吗?搞啥抽象类啊?"??
哈,这问题问得妙!其实很多兄弟学完C++回头看C,总觉得少了抽象类浑身难受。举个栗子:你想写个通用图形库,圆形、矩形都得有draw()方法,这时候用结构体函数指针模拟抽象类,那叫一个香!(敲黑板:??多态才是核心需求??)


一、先搞懂结构体函数指针这个"地基"

c复制
// 定义个"抽象类"结构体
typedef struct Shape {
    void (*draw)(void);  // 重点!函数指针占C位
    int type;
} Shape;

看到没???这个draw不是普通变量,而是等着被填坑的函数地址??。咱们的套路就是:具体图形(比如圆形)自己实现draw(),再把地址塞进这个指针里。


二、具体实现四步走(手把手教学版)

  1. ??定义抽象行为??
    先想清楚要抽象哪些方法,比如draw()、area()。这步最关键,就像装修前得先想好哪里要装插座!

  2. ??创建具体子类??

c复制
typedef struct Circle {
    Shape base;  // 继承的骚操作
    double radius;
} Circle;

// 实现专属draw方法
void circle_draw() {
    printf("画个圆,半径5cm\n"); 
}
  1. ??构造函数搞起来??
c复制
Circle* create_circle() {
    Circle* obj = malloc(sizeof(Circle));
    obj->base.draw = circle_draw;  // 灵魂所在!
    return obj;
}
  1. ??统一调用接口??
c复制
void render(Shape* shape) {
    shape->draw();  // 妙啊!不管传圆还是方都行
}

三、实战对比表格(建议收藏)

实现方式优点坑点提醒
结构体函数指针运行效率高,内存可控手动管理初始化比较麻烦
虚函数表更接近C++风格需要维护额外指针数组
宏定义封装代码量少调试起来要命

(摸着良心说)新手建议先从结构体函数指针入门,等玩溜了再搞虚函数表那些骚操作。


四、自问自答环节

??Q:为啥非要用函数指针?直接if-else判断类型不行吗???
A:兄弟,假如有100种图形,你得写100个if分支!用函数指针就像自动快递分拣机,来啥类型自动调对应方法,这逼格瞬间拉满啊!

??Q:这样搞会不会内存泄漏???
A:问得好!这就是C语言的刺激之处——记得用free()收尾,建议搭配valgrind检查。实在怕翻车的话...(小声)可以考虑转战Rust


五、个人掏心窝子的话

搞了十几年C开发,我发现这种模拟面向对象的方法??就像瑞士军刀??——某些场景下特别趁手,但别指望它能变成屠龙宝刀。最近给物联网设备写驱动时,用这招处理不同传感器类型,代码量直接砍半!

不过要提醒新手的是:??别为了炫技而炫技??。如果项目就两三个类型需要处理,老老实实用switch-case反而更清爽。编程嘛,合适的就是最好的!


最后的最后,给各位留个课后作业:试着给Shape结构体加个area()方法,计算不同图形的面积。搞定了的话...(露出老父亲般的微笑)恭喜你get了新技能!如果卡壳了,随时可以回来咱们唠唠~

本文由嘻道妙招独家原创,未经允许,严禁转载