1. 主页 > 小妙招

结构体+函数指针:C语言调用类成员方法实战

"我嘞个去!C语言连个class都没有,咋整出类的方法调用?" 别急着摔键盘,今天咱们就用手头现有的家伙事儿——??结构体配函数指针??,给你整出个花活来!这可不是我瞎吹,Linux内核里遍地都是这种操作,不信你往下瞅!


〇、先搞明白啥是"类方法"

??说白了就是把数据和操作打包??!举个栗子,咱要给"电饭煲"写个类:

  • 数据:当前温度、烹饪模式
  • 方法:煮饭()、保温()、预约()

在C语言里怎么玩???结构体装数据,函数指针当方法??,齐活!

c复制
typedef struct {
    int temperature;
    void (*cook)();  // 重点看这个!
} RiceCooker;

一、基础版:给结构体装"方法"

??手把手教你造个会叫的玩具狗??:

c复制
// 先定义方法
void wagTail() { printf("尾巴摇成电风扇!\n"); }

typedef struct {
    char name[20];
    void (*bark)();  // 方法指针
} ToyDog;

int main() {
    ToyDog dog1 = {"大黄", wagTail};
    dog1.bark();  // 看!方法调用!
}

??三个关键步骤??:

  1. 在结构体里挖个??函数指针??的坑
  2. 创建对象时??填坑??塞具体函数
  3. .->触发方法

??常见翻车现场??:

  • 忘记初始化函数指针就调用(直接段错误)
  • 函数签名不匹配(编译器可能不报错!)

二、升级版:带参数的方法

??搞个能算数的智能计算机??:

c复制
typedef struct {
    int (*calculate)(int, int);  // 带参数的函数指针
} SmartCalculator;

int add(int a, int b) { return a + b; }

int main() {
    SmartCalculator calc = {add};
    printf("3+5=%d\n", calc.calculate(3,5)); 
}

??参数传递的坑??:

  1. 函数指针声明必须和实际函数??严丝合缝??
  2. 参数类型不匹配会导致??玄学bug??
  3. 返回类型不对直接??程序崩溃??
无参数方法带参数方法
安全性较高较低
实用性有限强大
调试难度简单较难

三、终极版:实现多态

??整出会不同叫唤的猫狗??:

c复制
typedef struct {
    void (*speak)();
} Animal;

void dogSpeak() { printf("汪汪!\n"); }
void catSpeak() { printf("喵呜~\n"); }

int main() {
    Animal dog = {dogSpeak};
    Animal cat = {catSpeak};
    
    dog.speak();  // 输出汪汪
    cat.speak();  // 输出喵呜
}

??这不就是面向对象的多态???虽然简陋了点,但核心思想到位了!

??你可能会问??:"这和直接调用函数有啥区别?" 区别大了去了!这样做:

  1. ??行为和数据绑定??在一起
  2. 可以运行时??动态更换方法??
  3. 方便实现??插件式架构??

四、避坑指南

搞了八年嵌入式开发的老司机告诉你:

  1. ??内存对齐??问题:结构体里混着数据和函数指针时,记得用#pragma pack(1)
  2. ??类型检查??:建议用typedef定义函数指针类型
  3. ??空指针检测??:调用前务必检查指针是否为NULL

举个正经例子:

c复制
typedef void (*Action)();  // 先定义类型

struct Robot {
    Action dance;
};

void checkAction(struct Robot *r) {
    if(r->dance) {
        r->dance();
    } else {
        printf("没装舞蹈程序!\n");
    }
}

个人观点放送

很多新手总纠结"用C++不香吗",但真到了写单片机程序的时候——??ROM只剩2KB,RAM就512字节??,你还敢用C++的虚函数表?这时候结构体+函数指针的方案简直就是救命稻草!

再说个行业内幕:??Linux内核的file_operations结构体??就是靠这招实现驱动操作的。下次有人跟你说"C语言不能面向对象",直接把内核源码甩他脸上!咱们搞技术的,就得像玩乐高一样,用手头的积木搭出想要的功能,这才是真本事!

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