首页
学习
活动
专区
圈层
工具
发布

多态( C)
EN

Stack Overflow用户
提问于 2011-11-19 13:09:11
回答 4查看 59.4K关注 0票数 24

可能重复: 如何在C中模拟OO风格的多态性?

我试图用我所知道的语言中的例子来更好地理解多态性的概念;C中有多态性吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-11-19 14:22:57

这是Nekuromento的第二个例子,在我认为面向对象C的习语中是这样的:

animal.h

代码语言:javascript
复制
#ifndef ANIMAL_H_
#define ANIMAL_H_

struct animal
{
    // make vtable_ a pointer so they can be shared between instances
    // use _ to mark private members
    const struct animal_vtable_ *vtable_;
    const char *name;
};

struct animal_vtable_
{
    const char *(*sound)(void);
};

// wrapper function
static inline const char *animal_sound(struct animal *animal)
{
    return animal->vtable_->sound();
}

// make the vtables arrays so they can be used as pointers
extern const struct animal_vtable_ CAT[], DOG[];

#endif

cat.c

代码语言:javascript
复制
#include "animal.h"

static const char *sound(void)
{
    return "meow!";
}

const struct animal_vtable_ CAT[] = { { sound } };

dog.c

代码语言:javascript
复制
#include "animal.h"

static const char *sound(void)
{
    return "arf!";
}

const struct animal_vtable_ DOG[] = { { sound } };

main.c

代码语言:javascript
复制
#include "animal.h"
#include <stdio.h>

int main(void)
{
    struct animal kitty = { CAT, "Kitty" };
    struct animal lassie = { DOG, "Lassie" };

    printf("%s says %s\n", kitty.name, animal_sound(&kitty));
    printf("%s says %s\n", lassie.name, animal_sound(&lassie));

    return 0;
}

这是运行时多态的一个例子,因为这是方法解析发生的时候。

C1x添加了泛型选择,这使得通过宏进行编译时多态成为可能。以下示例取自C1x 4月草案第6.5.1.1节第5节:

代码语言:javascript
复制
#define cbrt(X) _Generic((X), \
    long double: cbrtl, \
    default: cbrt, \
    float: cbrtf \
)(X)

用于数学函数的类型通用宏已经在C99中通过报头tgmath.h获得,但是用户无法在不使用编译器扩展的情况下定义自己的宏。

票数 45
EN

Stack Overflow用户

发布于 2011-11-19 13:41:16

C中几乎所有运行时多态性的实现都将使用函数指针,因此这是基本的构建块。

下面是一个简单的例子,当过程运行时行为根据其参数变化时。

代码语言:javascript
复制
#include <stdio.h>

int tripple(int a) {
    return 3 * a;
}

int square(int a) {
    return a * a;
}

void transform(int array[], size_t len, int (*fun)(int)) {
    size_t i = 0;
    for(; i < len; ++i)
        array[i] = fun(array[i]);
}

int main() {
    int array[3] = {1, 2, 3};
    transform(array, 3, &tripple);
    transform(array, 3, &square);

    size_t i = 0;
    for (; i < 3; ++i)
        printf("%d ", array[i]);

    return 0;
}

使用函数指针,您可以创建虚拟表,并使用它创建“对象”,这些对象将被统一对待,但在运行时行为不同。

代码语言:javascript
复制
#include <stdio.h>

struct animal_vtable {
    const char* (*sound)();
};

struct animal {
    struct animal_vtable methods;
    const char* name;
};

const char* cat_sound() {
    return "meow!";
}

const char* dog_sound() {
    return "bark!";
}

void describe(struct animal *a) {
    printf("%s makes \"%s\" sound.\n", a->name, a->methods.sound());
}

struct animal cat = {{&cat_sound}, "cat"};
struct animal dog = {{&dog_sound}, "dog"};

int main() {
    describe(&cat);
    describe(&dog);

    return 0;
}
票数 21
EN

Stack Overflow用户

发布于 2011-11-19 13:21:07

C中没有对多态性的内在支持,但是有一些设计模式,使用函数指针、基类(结构)转换等等,它们可以提供动态分派的逻辑等效。GTK库就是一个很好的例子。

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

https://stackoverflow.com/questions/8194250

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档