面向对象的类C代码-无参数调用方识别

面向对象的类C代码-无参数调用方识别,c,oop,C,Oop,如果我有此设置: #include <stdlib.h> #define NEW_FOO ((foo_t*)malloc(sizeof(foo_t))) void foo_func(void); typedef struct { void (*foo) (void); } foo_t; int main(void) { foo_t *a = NEW_FOO; foo_t *b = NEW_FOO; a->foo = foo_func;

如果我有此设置:

#include <stdlib.h>
#define NEW_FOO ((foo_t*)malloc(sizeof(foo_t)))

void foo_func(void);

typedef struct {
    void (*foo) (void);
} foo_t;

int main(void) {
    foo_t *a = NEW_FOO;
    foo_t *b = NEW_FOO;
    a->foo = foo_func;
    b->foo = foo_func;
    a->foo();
    b->foo();
}

void foo_func(void) {
    // determine wheter a or b was called?
}
#包括
#定义新的\u FOO((FOO\u t*)malloc(sizeof(FOO\u t)))
void foo_func(void);
类型定义结构{
无效(*foo)(无效);
}富特;
内部主(空){
foo_t*a=新的;
foo_t*b=新的;
a->foo=foo_func;
b->foo=foo_func;
a->foo();
b->foo();
}
void foo_func(void){
//确定是调用a还是b?
}
然后我可以找出
a
b
foo_func
的调用者吗,严格来说没有像
self
this
这样的参数

返回地址应该在堆栈上,因此您应该能够以某种方式识别调用方,不是吗

我想到了一种可能的方法(它建立在上述思想的基础上):第一次通过
a->foo()
调用
foo_func
时(可能通过初始化函数,但为了保持简单,我们不必这样做),我假设将struct
a
的地址存储在某种指针数组中。与
b->foo()相同。然后,无论何时调用
a->foo()
b->foo()
,您都会将调用方结构的地址与数组中的内容进行比较,以确定调用
foo\u func()
的是
a
还是
b


只是我不知道这是否和/或如何可能,所以如果你们中的任何人能帮助我,我将非常高兴

我猜你对这些难看的建筑感到恼火,比如:

a->foo (a, arg0, arg1);
b->bar (b, arg0);
不幸的是,如果您想要实现多态方法的模拟,您所采用的编程风格确实会强制您采用这种风格。也许您可以实现一组宏,以便编写如下内容:

METHOD_CALL2 (foo, a, arg0, arg1);
METHOD_CALL1 (bar, b, arg0);
因此不必在调用中重复“对象”名称
a
b
,等等。我也见过这样做,但在我看来,它看起来并不漂亮,而且我确信它不再具有可维护性

因为这是C,不是C++,最后,你必须要有某种方式把你的等价代码< < /C> >传递给你的实现中的“方法”。你也许可以用宏和变长参数列表来掩饰它,但它必须以某种方式发生


但为什么要担心呢?这是惯用的C代码——采用面向对象方法的每个应用程序和库都将使用您希望避免的形式的构造。人们会理解你在做什么。我怀疑,试图掩饰它不会使您的代码更容易理解。

您能否提供一些背景信息,说明为什么需要它?最明显、最安全的解决方案是添加一个(void*)参数,并将其作为上下文传递给函数,即使您严格希望避免这样做。简单的回答是,您不能,除非您传递
foo_func()。。。至少,如果你想做一些它不是为之设计的事情——如果你真的想在C中模拟像
this
/
self
这样的OOP原则,你需要编写语言本身没有提供的所有样板文件,比如添加一个指向每个方法声明和调用的显式
this
/
self
指针。在这里你不能走你想走的捷径。包含函数指针的
struct
不是OOP的完整实现,这证明了.in
C
可以隐藏具有默认值的函数参数。因此,唯一的解决方案是
void foo\u func(const foo\u t*this)和<代码> A- > FO(A)< /COD>。但是如果你想要OOP IMO,最糟糕的是在C.中模仿它,你有C++,没有技巧。needed@P__J__也许是这样,但是普通C中的OOP是非常普遍的。例如,它是GTK及其所有支持库的主干。此外,我经常在嵌入式环境中工作,在那里可以选择C或机器代码;C++不是无所不在的。是的,宏的东西在这个例子中真的很奇怪。IMO.,我只是好奇如果有一个隐藏的,鬼鬼祟祟的回溯者的方法(我在汇编程序中是很有把握的),因为C是如此“愚蠢”。这也可能是我真正喜欢它的原因:P@rphii--我不确定这种情况是如何在汇编语言编程中出现的。一个成员是函数指针的结构在汇编中意味着什么?老实说,我对汇编不太了解,但就灵活性而言,这不是终极的东西吗?