c模拟虚函数表
从整体来看,笔者的做法与之前的模拟多态十分相似,毕竟c++多态的实现与虚函数密切相关
废话少说,see my code:
123456789101112kernel.c#include "kernel.h"#include
12345678910111213141516171819202122232425kernel.h:#ifndef UNTITLED_KERNEL_H#define UNTITLED_KERNEL_Hstruct shape_t { /*Virtual Method Table */ const struct shape_interface* const vtable;};struct shape_interface { void (*draw)();};void shape_draw(struct shape_t* obj); //obj->vtable->draw();#endif //UNTITLED_KERNEL_H
1234567891011121314151617181920212223242526272829303132333435363738394041try.c:#include
顺便一提,clion的编译器相当有趣
笔者在之前曾经写错了shape_interface (_t)结构体名称,但是笔者发现:
12//static const struct shape_interface_t *vtable = { draw1 } ;//static struct shape_t base = { &vtable };
改成这样也能运行
这是为什么呢?笔者推测,gcc应该是无法找到对于结构体,就把vtable当成了数组,加上*就成为了数组。然后&vtable就成为了二级指针,由于draw1本身就是一个指针,把它转成空指针什么的可以随便赋值。gcc在找不到对应结构体后,索性为base里的vtable开辟了一段空间,由于&vatble是二级指针,但是找不到对应地址指向,可能它在编译过程中被转为了一级空指针,且等于draw1本身,这样就能解释通了。(如果有c语言高手可以留言解答一下,笔者对c语言和编译器的处理所知甚少)
12345678910111213141516171819try.h:#ifndef UNTITLED_TRY_H#define UNTITLED_TRY_H#include "kernel.h"struct rectangle_t { struct shape_t* base; /* Reference to Base Class */ /* Rectangle specific Members */ int x; int y;};struct shape_t* shape_create_rectangle(); #endif //UNTITLED_TRY_H
在主函数中这样调用即可:
1234567891011121314151617main.c:#include "try.h"#include "kernel.h"int main() { struct shape_t* rectangle = shape_create_rectangle(); shape_draw(rectangle); return 0;}
接下来是重点,虚函数表的实现,可以适当改动try.c文件:
12345678910111213141516171819202122232425262728293031323334353637try.c://// Created by el on 2024/8/16.//#include
使用函数指针数组,就可以模拟出比较相近的虚函数表。
整个c程序的UML图如下:
其实这张图跟笔者前一篇模拟多态的文章思想是一样的。