用C语言编写面向对象代码的方法有哪些?特别是在多态方面。
还请参见此堆栈溢出问题https://stackoverflow.com/questions/415452/object-orientation-in-c。
发布于 2008-12-08 20:12:20
是。事实上,Axel免费提供了他的书“ANSI中的面向对象编程”,其中非常全面地涵盖了这个主题。
发布于 2008-12-08 20:06:09
既然你说的是多态性,那么是的,你可以,我们在C++出现前几年就在做类似的事情。
基本上,您可以使用struct
同时保存数据和函数指针列表,以指向该数据的相关函数。
因此,在一个通信类中,您将拥有一个打开、读、写和关闭调用,这些调用将作为结构中的四个函数指针来维护,以及对象的数据,如下所示:
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()
。
当您从该类“继承”时,只需更改指向您自己函数的指针。调用这些函数的每个人都会通过函数指针来实现这一点,从而给出您的多态性:
int stat = (commTcp.open)(commTcp, "bigiron.box.com:5000");
有点像手动表。
您甚至可以通过将指针设置为空-the行为来创建虚拟类,这与C++ (运行时的核心转储而不是编译时的错误)略有不同。
下面是演示它的一段示例代码。首先是顶级的阶级结构:
#include <stdio.h>
// The top-level class.
typedef struct sCommClass {
int (*open)(struct sCommClass *self, char *fspec);
} tCommClass;
然后我们有TCP‘子类’的函数:
// 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还包括:
// 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;
}
最后是一个测试程序来展示它的作用:
// 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;
}
这将产生输出:
Opening TCP: bigiron.box.com:5000
Opening HTTP: http://www.microsoft.com
因此您可以看到不同的函数正在被调用,这取决于子类。
发布于 2010-04-28 12:42:29
名称空间通常通过执行以下操作来完成:
stack_push(thing *)
而不是
stack::push(thing *)
class stack {
public:
stack();
void push(thing *);
thing * pop();
static int this_is_here_as_an_example_only;
private:
...
};
转到
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
并做:
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就像一个静态类变量--在一个类型的所有实例之间共享。所有的方法都是静态的,除了一些方法使用这个*
https://stackoverflow.com/questions/351733
复制相似问题