pax*_*blo 13
通常使用函数指针来完成它.换句话说,简单的结构既包含数据,也包含指向操作该数据的函数的指针.在Bjarne S来到现场之前,我们正在做那种事情.
因此,例如,在通信类中,您将进行打开,读取,写入和关闭调用,该调用将作为结构中的四个函数指针以及对象的数据进行维护,例如:
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 the data for the object goes here.
} tCommsClass;
tCommsClass commRs232;
commRs232.open = &rs232Open;
: :
commRs232.write = &rs232Write;
tCommsClass commTcp;
commTcp.open = &tcpOpen;
: :
commTcp.write = &tcpWrite;
Run Code Online (Sandbox Code Playgroud)
这些函数指针的初始化实际上将在"构造函数"中,例如rs232Init(tCommClass*),它将负责设置该特定对象的默认状态以匹配特定类.
当你从该类"继承"时,只需将指针更改为指向自己的函数即可.每个调用这些函数的人都会通过函数指针来完成它,为你提供多态性:
int stat = (commTcp.open)(commTcp, "bigiron.box.com:5000");
Run Code Online (Sandbox Code Playgroud)
有点像手动配置的vtable,用C++的说法.
您甚至可以通过将指针设置为NULL来拥有虚拟类 - 行为与C++略有不同,因为您可能在运行时获得核心转储而不是在编译时出错.
这是一段演示它的示例代码:
#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;
}
Run Code Online (Sandbox Code Playgroud)
// 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;
}
Run Code Online (Sandbox Code Playgroud)
这会产生输出:
Opening TCP: bigiron.box.com:5000
Opening HTML: http://www.microsoft.com
Run Code Online (Sandbox Code Playgroud)
所以你可以看到正在调用不同的函数,具体取决于子类.