我知道,因为 C 不是面向对象的,所以我们最接近方法的是在结构中使用函数指针。这只是一个思考练习,但是否有可能:
list.add(void* data)
没有将列表本身作为参数传递?
我知道:
list.add(list_t* list, void* data)
很容易实现,但是有什么方法可以使用 C 的任何部分以这种方式模拟方法吗?
我知道答案可能是否定的,但如果可以的话,请向我解释!谢谢。
这是我使用可变参数宏(C99) 得到的最漂亮的语法:
#define call(obj, method, ...) ((obj).method(&(obj), __VA_ARGS__))
struct class {
int a;
int (*method)(struct class* this, int b, int c);
};
int code(struct class* this, int b, int c) {
return this->a*b+c;
}
struct class constructor(int a) {
struct class result = {a, code};
return result;
}
#define call(obj, method, ...) ((obj).method(&(obj), __VA_ARGS__))
#include <stdio.h>
int main() {
struct class obj = constructor(10);
int result = call(obj, method, 2, 3);
printf("%d\n", result);
return 0;
}
不仅是实例方法,你甚至可以使用正确的库来拥有 CLOS 风格的泛型方法。Laurent Deniau 的 COS 库(另见论文:[链接])提供了一个完整的 OO 系统,您可以#include
立即开始使用;方法语法并不比任何其他函数调用重。
它显然也很快。作者声称已经在 Objective-C 中表达的类似代码上获得了性能优势(我会对这个声明本身持怀疑态度,但即使它们具有可比性,这也令人印象深刻)。
要模拟 OO 方法调用,您需要具有类或 vtable 指针的对象。例如,如果您list_t
包含一个funcs
指向包含函数指针的结构的成员,其中之一是add
,那么您的用法将是
list->funcs->add(list, data)
您可以在可变参数宏中捕获:
#define OO(obj, func, ...) (obj)->funcs->func(obj, __VA_ARGS__)
OO(list, add, data);
如果你想要一些简单的东西,你可以使用块语言扩展来实现结构成员函数。在这里写博客。
您可以使用块来 lambda 捕获关联的结构,模拟this指针。
这种方法没有虚拟分派,因此是否考虑这些真实对象取决于您。