c - 在常规 C 中非法多态属性的方法?

标签 c data-structures polymorphism

您好,我目前正在尝试学习 C,我想知道是否有一种方法可以在包含其他不同类型结构列表的结构中实现多态性?

一个例子是这样的:

  #include <stdlib.h>
#include <stdio.h>

typedef void (*update_t)(void *);

typedef struct entity entity_t;
typedef struct compA compA_t;
typedef struct compB compB_t;


struct compA{

    update_t update;
};

struct compB{

    update_t update;
};

struct entity{
    update_t update;
    int curSize;
    void **components;
};


void compA_update(void *c){
    printf("updating: componentA\n");
}

compA_t *compA_create(){
    compA_t *c = malloc(sizeof(compA_t));
    c->update = compA_update;
    return c; 
}

void compB_update(void *c){
    printf("updating: componentB\n");
}


compB_t *compB_create(){
    compB_t *c = malloc(sizeof(compB_t));
    c->update = compB_update;
    return c; 
}


void entity_update(void *en){
    entity_t *e = (entity_t *)en;
    for(int i = 0; i < e->curSize; i++){
        //would like to somehow update all the components with one line just iterating through the array but does not seem possible
    }
    return;
}



entity_t *entity_create(){
    entity_t *e = malloc(sizeof(entity_t));
    e->curSize = 0;
    e->update = entity_update;
    calloc(32, sizeof(void *));
    return e;
}

void add_component(entity_t *e, void *c){
    printf("%d\n", e->curSize);
    e->components[e->curSize] = c;
    e->curSize++;
    return;
}




int main(void){

    entity_t *e = entity_create();
    compA_t *a = compA_create();
    compB_t *b = compB_create();
    add_component(e, a);
    add_component(e, b);

    e->update(e);

    return 0;
}

到目前为止,我解决这个问题的方法是用元组结构的空指针数组解决的,它包含一个枚举类型,它标识结构以及结构本身,然后在一个潜在的更新函数中,一个相当丑陋的 switch 语句必须为每个特定类型用一个案例来实现。

有更好的方法吗?因为如果数组中有很多不同的类型,开关方法会很快变得相当疯狂。这意味着必须为每种类型显式添加案例,并且每个案例都做完全相同的事情,在本例中是调用名为“更新”的函数指针。

最佳答案

你可以尝试数据多态性而不是函数指针。也就是说,使用相同的代码,不同的数据会产生不同的行为。

例如一个简单的多态行为:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>

typedef const char* ccstr;

typedef struct animal_attr_t
{
    bool is_body_segmented;
    float gill_completeness;
    float lung_completeness;
} animal_attr_t;

typedef struct species
{
    ccstr name, kingdom, domain;

    animal_attr_t animal_attr[0];
} species;

void initialize_species_base(species *this, ccstr name, ccstr kingdom, ccstr domain)
{
    this->name = name;
    this->kingdom = kingdom;
    this->domain = domain;
}

void initialize_animal_attr(animal_attr_t *this, bool is_body_segmented, float gill_completenss, float lung_completeness)
{
    this->is_body_segmented = is_body_segmented;
    this->gill_completeness = gill_completenss;
    this->lung_completeness = lung_completeness;
}

void print_species(species*);

int main(int argc, char *argv[])
{
    species *yeast = calloc(sizeof(species), 1);
    assert(yeast);

    initialize_species_base(yeast, "yeast", "fungus", "eukaryote");

    print_species(yeast);

    species *dog = calloc(sizeof(species) + sizeof(animal_attr_t), 1);
    assert(dog);

    initialize_species_base(dog, "dog", "animal", "eukaryote");
    initialize_animal_attr(dog->animal_attr, true, 0.0f, 1.0f);

    print_species(dog);

    free(yeast);
    free(dog);
}

void print_species(species *this)
{
    printf("name = %s, kingdom = %s, domain = %s",
           this->name, this->kingdom, this->domain);

    if (strcmp(this->kingdom, "animal") == 0) {
        animal_attr_t *ani_attr = this->animal_attr;
        printf(", has %s, %f completeness of gill, %f completeness of lung",
               ani_attr->is_body_segmented ? "segmented body" : "unsegmented body",
               ani_attr->gill_completeness, ani_attr->lung_completeness);
    }

    printf(".\n");
}

yeastdog是两种完全不同的类型,但是species是统一表达的,print_species 具有多态行为。

关于c - 在常规 C 中非法多态属性的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53239278/

相关文章:

C,open_MPI,用户定义的结构类型未正确传递

algorithm - 带快速插入的矩形的空间索引

C++,如何返回基类,然后将其转换为派生类?

c++ - 实现八叉树

java - 随机实例化派生类

c++ - 为什么我们实际上需要运行时多态性?

c - 返回C中的指针,在字符串中查找值

c - 从文件中读取结构内的结构

c - 在c中显示以 '*'分隔的正数的质因数

algorithm - 如下所述,为场景 A 和 B 选择哪种数据结构