C语言模拟对象、方法:“函数指针+结构体“复用函数指针指向的函数体

preface

c语言的函数指针+结构体 模拟对象和方法,复用函数指针指向的函数体

助手思考过程

(本轮为直接概念问答,未触发独立的 extended-thinking 块;回答基于对 C 语言对象模拟机制的直接组织:先给核心结论「复用同一份函数体」,再用可运行代码证明 a.bark == b.bark,然后强调 self 参数不可省,最后升级到 vtable 的工程做法,并关联到本仓库 业务目录 的 内存表 引擎复用思路。)

助手回复

核心结论

用「结构体存数据 + 函数指针存方法」模拟对象时:

  • 函数体(代码)只有一份 ,存在于代码段(.text),被所有"对象"共享;
  • 每个对象各有一份数据(结构体实例,在堆/栈上);
  • 函数指针只是指向那唯一一份函数体的地址,不同对象的同名指针通常指向同一个函数。

这和 C++ 的成员函数机制其实一样:C++ 的成员函数也是一份代码,靠隐藏的 this 指针区分是哪个对象。

用代码看清楚

c 复制代码
typedef struct Dog {
    char name[32];
    void (*bark)(struct Dog *self);   // 函数指针 = 方法
} Dog;

// 唯一的一份函数体,复用给所有 Dog
void dog_bark(Dog *self) {
    printf("%s: wang!\n", self->name);   // 靠 self 区分数据
}

int main(void) {
    Dog a = {"a", dog_bark};
    Dog b = {"b", dog_bark};

    a.bark(&a);   // 输出 a: wang!
    b.bark(&b);   // 输出 b: wang!

    // 关键:两个对象的函数指针指向同一地址
    printf("%d\n", a.bark == b.bark);   // 1,同一个函数体
}

a.bark 和 b.bark 值相同 ------ 证明代码复用了同一函数体 ,区别只在传入的 self(数据)不同。

关键点:self 参数不可省

C 没有 C++ 的隐式 this。函数体要访问"当前对象"的数据,必须显式把对象指针传进去 (惯例命名 self/this)。否则一份共享的函数体无从知道该操作哪个实例的数据。

更省内存的做法:vtable

如果每个对象都在结构体里塞一堆函数指针,指针本身也会被每个实例复制一份,浪费内存。工程上常把方法集中到一张"虚表"里,对象只存一个指向虚表的指针:

c 复制代码
typedef struct Animal Animal;

typedef struct {                       // 虚表:全类共享一份
    void (*speak)(Animal *self);
    void (*eat)(Animal *self);
} AnimalVTable;

struct Animal {
    const AnimalVTable *vtbl;          // 只存一个指针
    char name[32];
};

static const AnimalVTable DOG_VT = { dog_speak, dog_eat };
// 所有 Dog 实例的 vtbl 都指向 &DOG_VT

这就是 C++ 虚函数、以及 Linux 内核(如 file_operations、struct device)的实现套路 ------ 函数体一份、虚表一份、数据每对象一份,复用最大化。


一句话总结:是的,函数指针只是"地址",指向的函数体被所有对象复用;真正每个对象独立的是结构体里的数据,靠显式 self 参数把数据喂给那份共享的代码。

顺带一提,这套模式在你这个 app 仓库里也有体现 ------ 比如 app业务 的表通过 TABLE_DESC/KEY/FIELD 宏描述,再由统一的 内存表 引擎代码去操作不同表的数据,思路是相通的(用一份引擎代码复用到多张表)。需要的话我可以在仓库里找几个具体例子讲。

相关推荐
老花眼猫16 分钟前
数学艺术图案画-曼陀罗(93)
c语言·经验分享·青少年编程·课程设计
泡海椒34 分钟前
JQuick-Excel dateFormat 转换实战:日期值与 FORMAT 显示格式的边界
开发语言·python·excel
水饺编程1 小时前
第1章:下载 Linux 0.12 内核
linux·c语言·汇编·ubuntu
白杨尚青1 小时前
C++入门篇(十三):vector(上)——动态数组:构造、空间增长与迭代器失效
开发语言·c++·笔记·算法·stl
江江爱编程1 小时前
java零基础保姆级教学01
java·开发语言
沐晓时光1 小时前
C语言入门,深入理解指针(2)
c语言·开发语言
Logic1011 小时前
C语言/数据结构贪心算法题解:字符串趋同——逐位统计最高频率求最小修改代价
c语言·数据结构·贪心算法·字符串·时间复杂度·频率统计·算法题
水饺编程1 小时前
第1章:开发环境搭建,在 Windows 中安装 Git
linux·c语言·汇编·git·ubuntu
2601_962885721 小时前
如何用 Python 做均线粘合选股?(多头发散前的变盘候选)
开发语言·python
2601_962071572 小时前
类变量和全局变量的隔离性有什么区别?
java·开发语言·jvm