gcc (GCC) 4.7.2
c89
I am doing some practicing on using some object-oriented style in C. As I want to do this for some of our larger projects.
However, in my code below I have a parent structure car and a child sports_cars. However, all the commom attibutes or the car struct will be present in the child structures.
There is one question I have and that is the init and destory functions. As they are commom I want my child structures to heritant the init and the destroy. But I think I am doing it wrong.
car->init = init_car;
As I have the init function pointer pointing to init_car, doesn’t look right to me.
Many thanks for any suggestions,
#include <stdio.h>
#include <stdlib.h>
typedef struct tag_car car_t;
struct tag_car {
size_t wheels;
char *name;
void (*init)(void *self);
void (*destroy)(void *self);
size_t (*wheels_get)(void *self);
void (*wheels_set)(void *self, size_t num_wheels);
};
typedef struct tag_sports sports_t;
struct tag_sports {
car_t base_car;
size_t top_speed;
size_t (*top_speed_get)(void *self);
void (*top_speed_set)(void *self, size_t max_top_speed);
};
void destroy_car(void *self)
{
car_t *car = self;
free(car);
}
void init_car(void *self)
{
car_t *car = car;
car->wheels = 4;
car->name = NULL;
car->init = init_car;
car->destroy = destroy_car;
}
size_t wheels_count_get(void *self)
{
car_t *car = self;
return car->wheels;
}
void wheels_count_set(void *self, size_t num_wheels)
{
car_t *car = self;
car->wheels = num_wheels;
}
size_t sports_top_speed_get(void *self)
{
sports_t *sports_car = self;
return sports_car->top_speed;
}
void sports_top_speed_set(void *self, size_t max_top_speed)
{
sports_t *sports_car = self;
sports_car->top_speed = max_top_speed;
}
sports_t* init_sports()
{
sports_t *sports_car = malloc(sizeof(sports_t));
/* Parent struct */
sports_car->base_car.init = init_car;
sports_car->base_car.destroy = destroy_car;
sports_car->base_car.wheels_get = wheels_count_get;
sports_car->base_car.wheels_set = wheels_count_set;
/* Child struct */
sports_car->top_speed_set = sports_top_speed_set;
sports_car->top_speed_get = sports_top_speed_get;
return sports_car;
}
int main(void)
{
sports_t *farreri = init_sports();
sports_t *lamborghini = init_sports();
farreri->base_car.wheels_set(farreri, 10);
farreri->top_speed_set(farreri, 240);
printf("farreri has wheel count [ %ld ]\n", farreri->base_car.wheels_get(farreri));
printf("Farreri has a top speed [ %ld ]\n", farreri->top_speed_get(farreri));
lamborghini->base_car.wheels_set(lamborghini, 6);
lamborghini->top_speed_set(lamborghini, 220);
printf("lamborghini has wheel count [ %ld ]\n", lamborghini->base_car.wheels_get(lamborghini));
printf("Lamborghini has a top speed [ %ld ]\n", lamborghini->top_speed_get(lamborghini));
farreri->base_car.destroy(farreri);
lamborghini->base_car.destroy(lamborghini);
return 0;
}
In your
init_carthe linesshouldn’t be present. You’re mixing the construction behavior with initialization. In C++ the constructor is responsible for doing both; if you want to simulate the same behavior, you should expose allocation interface (e.g., call it
construct) which will allocate the memory (yourmallocand also setting the object “methods” to the appropriate functions) and initialization interface (which will do the init stuff:car->wheels = 4; car->name = NULL;). The allocation method can call the initialization method to achieve the C++ behavior. You’ll have something like this:If you don’t want the construction to init the object, just don’t invoke the initialization from
construct, invoke it after the construction by callingsports_car->base_car.init.