c - C中vtable的单独结构
问题描述
在 C 中执行 OOP 的自然方法是执行以下操作:
#include <stddef.h>
/* stream operations */
struct _src {
/** open stream. Return true on success */
bool (*open)(struct _src *src, const char *fspec);
/** close stream. Return true on success */
bool (*close)(struct _src *src);
/** Returns the actual size of buffer read (<=len), or 0 upon error */
size_t (*read)(struct _src *src, void *buf, size_t len);
/* hold the actual FILE* in the case of file stream */
void *data;
};
有时我看到操作位于单独的结构中,并且设计如下:
#include <stddef.h>
struct _src {
/* vtable */
const struct _src_ops *ops;
/* hold the actual FILE* in the case of file stream */
void *data;
};
/* stream operations */
struct _src_ops {
/** open stream. Return true on success */
bool (*open)(struct _src *src, const char *fspec);
/** close stream. Return true on success */
bool (*close)(struct _src *src);
/** Returns the actual size of buffer read (<=len), or 0 upon error */
size_t (*read)(struct _src *src, void *buf, size_t len);
};
以一种方式或另一种方式做的全部意义是什么?
解决方案
似乎有两个好处:
const
限定符阻止用户有意或无意地重定向函数指针。这将使函数指针本身成为只读的。- 拥有一个指针可以让函数成为一个单独的“单例”实例,因为这些函数对于每个结构对象都是相同的,并且只需要分配一次。
但是,使用函数指针进行 OOP 相当粗糙,并且在您绝对确定需要多态性的情况下才有意义。没有this
指针,因此您最终会遇到笨拙的语法,例如foo.func(&foo, ...)
. 值得注意的是,编写“对象点成员”的可能性是一种语言语法,与 OO 设计本身无关。
总体而言,花费大量精力来实现有点罕见和专门的 OO 概念(继承/多态),同时忽略了更重要的 OO 概念(私有封装),这很奇怪。
根据我的经验,最好只使用普通函数但实现不透明类型并将实例作为参数传递给结构。当你真正需要它时处理继承。
推荐阅读
- java - 在自己的类中实例化对象
- arrays - 模板只包含上下文传递的数组的最后一个元素
- r - 部分 pivot_longer 的更好解决方案
- javascript - 如何使用 VeeValidate 3 和 vue.js 制定自定义验证规则
- r - R countif 并在指定向量中匹配元素的多列上求和
- alexa - Alexa技能错误“请求的技能响应有问题”
- javascript - 使用 JavaScript 从控制台更改 HTML 列表项的 innerText
- c++ - 如何根据向量中的内容移动元素?
- ios - 如何使用 Buck 为 Swift 应用程序构建 SBTUITestTunnel?
- web-scraping - 如何将单词(单词中的数字)转换为scrapy中的整数?