Вы можете попробовать полиморфизм данных вместо указателя функции. То есть разные данные приводят к разному поведению, используя один и тот же код.
Например, простое полиморфное поведение:
#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");
}
yeast
и dog
- это 2 совершенно разных типа, но с species
это выражается унифицированным образом, а print_species
имеет полиморфное поведение.