C中的多态性

Ped*_*ges 5 c polymorphism

我正在用C语言设计一个操作几何图形的程序,如果每种类型的图形都可以被相同的图元操纵,那将是非常方便的.

我怎么能在C中这样做?

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)

所以你可以看到正在调用不同的函数,具体取决于子类.

  • @Robert,我想称赞,但用一位不朽的科学家的话来说,"我到目前为止看到的原因是因为我站在了巨人的肩膀上". (5认同)