是否可以在C中模拟对象/实例方法?

时间:2013-06-27 08:19:10

标签: c oop

我知道,因为C不是面向对象的,所以我们最接近方法的是在结构中使用函数指针。这只是一个思考练习,但有可能有:

list.add(void* data)

没有将列表本身作为参数传递

我知道:

list.add(list_t* list, void* data)

很容易实现,但有没有办法,使用C的任何部分,以这种方式模拟一个方法?

我认识到答案可能是否定的,但如果可以,请向我解释!感谢。

4 个答案:

答案 0 :(得分:6)

这是我使用可变参数宏(C99)获得的最漂亮的语法:

#define call(obj, method, ...) ((obj).method(&(obj), __VA_ARGS__))

usage (click for ideone)

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;
}

答案 1 :(得分:2)

不仅是实例方法,而且您甚至可以使用正确的库具有CLOS样式的泛型方法。 Laurent Deniau's COS library(另见论文:[link])提供了一个完整的OO系统,您可以#include并立即开始使用;方法语法并不比任何其他函数调用重。

它显然也很快;作者声称在Objective-C中表达的类似代码已经获得了性能优势(我会用一小撮盐来宣称自己,但即使它们具有可比性,令人印象深刻)。

答案 2 :(得分:1)

要模拟OO方法调用,您需要具有class或vtable指针的对象。如果您的list_t包含一个指向包含函数指针的结构的funcs成员,其中一个是add,那么您的用法将是

list->funcs->add(list, data)

您可以在可变参数宏中捕获:

#define OO(obj, func, ...) (obj)->funcs->func(obj, __VA_ARGS__)

OO(list, add, data);

答案 3 :(得分:0)

如果您想要简单的东西,可以使用blocks语言扩展来实现struct成员函数。博客here

您可以使用块来捕获关联的结构,模拟 this 指针。

这种方法没有虚拟调度,因此您是否考虑这些真实对象取决于您。