2012-11-22 2 views
0
gcc (GCC) 4.7.2 
c89 

Je pratique un certain style orienté objet en C. Je veux faire cela pour certains de nos grands projets.en utilisant la programmation oop in c

Cependant, dans mon code ci-dessous j'ai une voiture de structure parent et un enfant sports_cars. Cependant, tous les attributs communs ou la structure de la voiture seront présents dans les structures de l'enfant.

Il y a une question que j'ai, c'est-à-dire les fonctions init et destory. Comme ils sont commom je veux que mes structures d'enfant à l'héritier l'init et le détruisent. Mais je pense que je le fais mal. Comme j'ai le pointeur de la fonction init pointant sur init_car, ne me regarde pas correctement.

Un grand merci pour toutes les 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; 
} 
+1

Vous n'avez pas implémenté correctement le * polymorphisme *, une fonctionnalité clé oop. Vous laissez maintenant le code client utiliser * base_car * mais cela ne fonctionne pas lorsque vous passez une lamborghini * à une fonction qui prend une voiture *. Un niveau supplémentaire d'indirection est nécessaire, regardez comment les tables v sont utilisées en C++. –

Répondre

2

Dans vos init_car les lignes

car->init = init_car; 
car->destroy = destroy_car; 

ne devraient pas être présents. Vous mélangez le comportement de construction avec l'initialisation. En C++, le constructeur est responsable de faire les deux; Si vous voulez simuler le même comportement, vous devez exposer l'interface d'allocation (par exemple, appelez construct) qui va allouer la mémoire (votre malloc et également la définition des objets "méthodes" aux fonctions appropriées) et l'interface d'initialisation (qui fera la init stuff: car->wheels = 4; car->name = NULL;). La méthode d'allocation peut appeler la méthode d'initialisation pour atteindre le comportement C++. Vous aurez quelque chose comme ceci:

void init_car(void *self) 
{ 
    car_t *car = self; 

    car->wheels = 4; 
    car->name = NULL; 
} 

sports_t* construct() 
{ 
    sports_t *sports_car = malloc(sizeof(sports_t)); 

    /* Set the methods */ 
    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; 

    /* initialize the object */ 
    sports_car->base_car.init(); 

    return sports_car; 
} 

int main(void) 
{ 
    /* construct and init the objects */ 
    sports_t *ferrari = construct(); 
    sports_t *lamborghini = construct(); 

    /* do your manipulations */ 

    /* destroy the objects */ 
    ferrari->base_car.destroy(farreri); 
    lamborghini->base_car.destroy(lamborghini); 

    return 0; 
} 

Si vous ne voulez pas la construction à init l'objet, il suffit de ne pas invoquer l'initialisation de construct, invoquez après la construction en appelant sports_car->base_car.init.

0

Vous pouvez utiliser un pointeur vers une structure qui contient des pointeurs vers des fonctions - tout comme [hidden] vtable dans C++. En outre, car_t *car = car; est incorrect, je suppose que vous avez signifié 'self'