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

我正在做一些C中使用某種面向對象風格的練習。因爲我想爲我們的一些大型項目做到這一點。在c編程中使用oop

但是,在我的代碼下面我有一個父母結構的車和一個小孩sports_cars。但是,所有通用屬性或汽車結構都將存在於子結構中。

我有一個問題,那就是init和destory函數。因爲它們很普通,所以我希望我的孩子結構能夠將init和destroy破壞掉。但我認爲我做錯了。

car->init = init_car; 

由於我有指向init_car的init函數指針,看起來並不正確。

非常感謝您的任何建議,

#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

你沒有正確實現*多態*,一個關鍵的oop功能。您現在將其留給客戶端代碼使用* base_car *,但當您將lamborghini *傳遞給需要汽車*的功能時無法工作。需要一個額外的間接級別,看看如何在C++中使用v-表。 –

回答

2

在你init_car

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

不應存在。您將構建行爲與初始化混合在一起。在C++中,構造函數負責執行兩者;如果你想模擬相同的行爲,你應該公開分配接口(例如,稱爲construct),它將分配內存(你的malloc,並設置對象「方法」爲適當的功能)和初始化接口(這將做init stuff:car->wheels = 4; car->name = NULL;)。分配方法可以調用初始化方法來實現C++行爲。你會是這樣的:

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; 
} 

如果你不想建設初始化對象,只是不從construct調用初始化,通過調用sports_car->base_car.init施工後調用它。

0

你可以使用指針結構,它包含指向函數的指針 - 就像C++中的[hidden] vtable一樣。另外,car_t *car = car;是不正確的,我想你的意思是'自我'