【问题标题】:Experiment: Object Oriented C? [duplicate]实验:面向对象的C? [复制]
【发布时间】:2011-05-05 11:01:38
【问题描述】:

可能重复:
Can you write object oriented code in C?

嗨!

只是为了好玩,这两天我一直在尝试用纯 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 宏。

edit> 忘了说——我不希望每个实例都在其结构中包含函数指针。这会给我方法语法,但这意味着一个 4 字节的数据对象将有十几个函数指针复制到每个实例。有点像作弊=P哈哈

提前致谢!

【问题讨论】:

标签: c object macros


【解决方案1】:

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找到。

回应您的评论:

我不希望每个实例中都包含函数。

你可能是对的。当单个类的每个实例都相同时,没有必要复制该信息。

有一个简单的方法。与其让每个实例都携带自己的一组函数指针,不如为该类创建一个保存它们的结构,然后每个实例都获得一个指向该结构的指针。

这将以必须执行两级间接调用函数的(最小)成本节省相当多的空间。

【讨论】:

  • 感谢您的回答,但我忘了说,我不希望每个实例中都包含函数。想象一下,如果每个列表节点,或包装的整数,或其他任何东西,必须包含 20 个函数指针!
  • 好吧,那么你可以在结构中有一个 single 指针,它指向一个特定于类的函数指针数组。您将不得不使用双重间接调用函数而不是单间接调用,但这会节省空间。我会将其添加到我的答案中。
  • 对不起,我刚刚读到了!是的,我不担心 无法 使用这些功能。我可以做(假设一个指向对象中的类的指针称为'f') object->f->fun(object);但它看起来很丑哈哈。我正在尝试将自己的方式宏化到 object.fun(); -- 不知道有没有可能。
猜你喜欢
  • 2011-03-05
  • 2012-05-27
  • 2010-11-15
  • 2011-06-21
  • 1970-01-01
  • 2012-03-02
  • 2023-04-05
  • 1970-01-01
  • 2011-04-01
相关资源
最近更新 更多