代码之家  ›  专栏  ›  技术社区  ›  salezica

实验:面向对象C?[副本]

  •  5
  • salezica  · 技术社区  · 14 年前

    可能重复:
    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字节的数据对象将有十几个函数指针复制到每个实例。这有点像作弊=哈哈

    提前谢谢!

    1 回复  |  直到 7 年前
        1
  •  13
  •   Community Ian Goodfellow    7 年前

    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 .

    针对您的评论:

    你可能是对的。当一个类的每个实例的信息都相同时,就没有必要重复这些信息了。

    有一个简单的办法。不是让每个实例都携带自己的函数指针集,而是为类创建一个包含这些指针的结构,然后每个实例都获得指向该结构的指针。

    这将节省相当多的空间,代价是(最小的)必须执行两级间接寻址来调用函数。