首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何用C语言编写面向对象的代码?

如何用C语言编写面向对象的代码?
EN

Stack Overflow用户
提问于 2008-12-08 20:02:40
回答 32查看 368.4K关注 1票数 532

用C语言编写面向对象代码的方法有哪些?特别是在多态方面。

还请参见此堆栈溢出问题https://stackoverflow.com/questions/415452/object-orientation-in-c

EN

回答 32

Stack Overflow用户

回答已采纳

发布于 2008-12-08 20:12:20

是。事实上,Axel免费提供了他的书“ANSI中的面向对象编程”,其中非常全面地涵盖了这个主题。

票数 383
EN

Stack Overflow用户

发布于 2008-12-08 20:06:09

既然你说的是多态性,那么是的,你可以,我们在C++出现前几年就在做类似的事情。

基本上,您可以使用struct同时保存数据和函数指针列表,以指向该数据的相关函数。

因此,在一个通信类中,您将拥有一个打开、读、写和关闭调用,这些调用将作为结构中的四个函数指针来维护,以及对象的数据,如下所示:

代码语言:javascript
运行
AI代码解释
复制
typedef struct {
    int (*open)(void *self, char *fspec);
    int (*close)(void *self);
    int (*read)(void *self, void *buff, size_t max_sz, size_t *p_act_sz);
    int (*write)(void *self, void *buff, size_t max_sz, size_t *p_act_sz);
    // And data goes here.
} tCommClass;

tCommClass commRs232;
commRs232.open = &rs232Open;
: :
commRs232.write = &rs232Write;

tCommClass commTcp;
commTcp.open = &tcpOpen;
: :
commTcp.write = &tcpWrite;

当然,上面的代码段实际上是在一个“构造函数”中,比如rs232Init()

当您从该类“继承”时,只需更改指向您自己函数的指针。调用这些函数的每个人都会通过函数指针来实现这一点,从而给出您的多态性:

代码语言:javascript
运行
AI代码解释
复制
int stat = (commTcp.open)(commTcp, "bigiron.box.com:5000");

有点像手动表。

您甚至可以通过将指针设置为空-the行为来创建虚拟类,这与C++ (运行时的核心转储而不是编译时的错误)略有不同。

下面是演示它的一段示例代码。首先是顶级的阶级结构:

代码语言:javascript
运行
AI代码解释
复制
#include <stdio.h>

// The top-level class.

typedef struct sCommClass {
    int (*open)(struct sCommClass *self, char *fspec);
} tCommClass;

然后我们有TCP‘子类’的函数:

代码语言:javascript
运行
AI代码解释
复制
// 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;
}

此外,HTTP还包括:

代码语言:javascript
运行
AI代码解释
复制
// Function for the HTTP 'class'.

static int httpOpen (tCommClass *http, char *fspec) {
    printf ("Opening HTTP: %s\n", fspec);
    return 0;
}
static int httpInit (tCommClass *http) {
    http->open = &httpOpen;
    return 0;
}

最后是一个测试程序来展示它的作用:

代码语言:javascript
运行
AI代码解释
复制
// Test program.

int main (void) {
    int status;
    tCommClass commTcp, commHttp;

    // Same 'base' class but initialised to different sub-classes.

    tcpInit (&commTcp);
    httpInit (&commHttp);

    // Called in exactly the same manner.

    status = (commTcp.open)(&commTcp, "bigiron.box.com:5000");
    status = (commHttp.open)(&commHttp, "http://www.microsoft.com");

    return 0;
}

这将产生输出:

代码语言:javascript
运行
AI代码解释
复制
Opening TCP: bigiron.box.com:5000
Opening HTTP: http://www.microsoft.com

因此您可以看到不同的函数正在被调用,这取决于子类。

票数 376
EN

Stack Overflow用户

发布于 2010-04-28 12:42:29

名称空间通常通过执行以下操作来完成:

代码语言:javascript
运行
AI代码解释
复制
stack_push(thing *)

而不是

代码语言:javascript
运行
AI代码解释
复制
stack::push(thing *)

若要将C结构转换为类似于C++类的内容,您可以转换:

代码语言:javascript
运行
AI代码解释
复制
class stack {
     public:
        stack();
        void push(thing *);
        thing * pop();
        static int this_is_here_as_an_example_only;
     private:
        ...
};

转到

代码语言:javascript
运行
AI代码解释
复制
struct stack {
     struct stack_type * my_type;
     // Put the stuff that you put after private: here
};
struct stack_type {
     void (* construct)(struct stack * this); // This takes uninitialized memory
     struct stack * (* operator_new)(); // This allocates a new struct, passes it to construct, and then returns it
     void (*push)(struct stack * this, thing * t); // Pushing t onto this stack
     thing * (*pop)(struct stack * this); // Pops the top thing off the stack and returns it
     int this_is_here_as_an_example_only;
}Stack = {
    .construct = stack_construct,
    .operator_new = stack_operator_new,
    .push = stack_push,
    .pop = stack_pop
};
// All of these functions are assumed to be defined somewhere else

并做:

代码语言:javascript
运行
AI代码解释
复制
struct stack * st = Stack.operator_new(); // Make a new stack
if (!st) {
   // Do something about it
} else {
   // You can use the stack
   stack_push(st, thing0); // This is a non-virtual call
   Stack.push(st, thing1); // This is like casting *st to a Stack (which it already is) and doing the push
   st->my_type.push(st, thing2); // This is a virtual call
}

我没有执行析构函数或删除,但它遵循相同的模式。

this_is_here_as_an_example_only就像一个静态类变量--在一个类型的所有实例之间共享。所有的方法都是静态的,除了一些方法使用这个*

票数 95
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/351733

复制
相关文章

相似问题

领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文