嗨!
只是为了它的乐趣,我在最后两天一直在尝试用纯C创建一个非常简单,非常简单的对象环境。我一直在用宏,动态链接,类型描述结构和之类的,我到达了以下内容:
string_o str = new(String, "hello world");
list_o list = new(List);
List.pushf(list, str);
printf("In the list: \"%s\"\n",
String.text(List.popf(list)));
delete(list);
delete(str);
看起来和工作有点好,但我无法找到伪造实例方法的方法。我不能越过Class.function(instance)
,不能没有功能名称的全局宏替换,这会破坏封装的目的。
同样,这是一个实验,只是为了挑战和乐趣=)。你能帮我找出办法吗?我不想使用额外的预处理,只使用普通的C和GCC宏。
编辑>忘了说 - 我不希望每个实例都在其结构中包含函数指针。这会给我方法语法好,但这意味着一个4字节的数据对象会有十几个函数指针复制到每个实例。这有点像作弊= P哈哈
提前致谢!
答案 0 :(得分:12)
C中的面向对象通常使用函数指针完成。这意味着一个结构不仅包含实例的数据,还包含要调用的函数。
这是在C中进行继承和多态的最简单方法。举例来说,这是一个面向对象的通信示例。
它只有一个方法open
,但您可以看到TCP和HTML子类的不同之处。通过设置一个特定于类的函数的初始化例程,您将获得多态性。
#include <stdio.h>
// The top-level class.
typedef struct _tCommClass {
int (*open)(struct _tCommClass *self, char *fspec);
} tCommClass;
// Function for the TCP class.
static int tcpOpen (tCommClass *tcp, char *fspec) {
printf ("Opening TCP: %s\n", fspec);
return 0;
}
static int tcpInit (tCommClass *tcp) {
tcp->open = &tcpOpen;
return 0;
}
// Function for the HTML class.
static int htmlOpen (tCommClass *html, char *fspec) {
printf ("Opening HTML: %s\n", fspec);
return 0;
}
static int htmlInit (tCommClass *html) {
html->open = &htmlOpen;
return 0;
}
// Test program.
int main (void) {
int status;
tCommClass commTcp, commHtml;
// Same base class but initialized to different sub-classes.
tcpInit (&commTcp);
htmlInit (&commHtml);
// Called in exactly the same manner.
status = (commTcp.open)(&commTcp, "bigiron.box.com:5000");
status = (commHtml.open)(&commHtml, "http://www.microsoft.com");
return 0;
}
可以找到更完整的答案here。
回应你的评论:
我不希望每个实例中包含的函数。
你可能是对的。如果对于单个类的每个实例都相同,则不必复制该信息。
有一个简单的方法。您不是让每个实例都携带自己的一组函数指针,而是创建一个为该类保存它们的结构,然后每个实例都获得一个指向该结构的指针。
这样可以节省相当多的空间,只需花费两个级别的间接来调用一个函数。(/ p>