0
gcc (GCC) 4.7.2
c89

私は C でいくつかのオブジェクト指向スタイルを使用する練習を行っています。これは、いくつかの大規模なプロジェクトでこれを行いたいためです。

ただし、以下のコードでは、親構造 car と子 sports_cars があります。ただし、すべての共通属性または car 構造体は子構造に存在します。

私が持っている質問が 1 つあります。それは 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;
}
4

2 に答える 2

2

あなたinit_carの行で

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

存在すべきではありません。構築動作と初期化を混在させています。C++ では、コンストラクターが両方を実行します。同じ動作をシミュレートしたい場合はconstruct、メモリを割り当てる割り当てインターフェイス (たとえば、それを呼び出す) (mallocおよびオブジェクトの「メソッド」を適切な関数に設定する) と初期化インターフェイス (初期化を行う) を公開する必要があります。 : 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ます。

于 2012-11-22T11:51:16.923 に答える
0

C++の[hidden]vtableのように、関数へのポインターを含む構造体へのポインターを使用できます。また、car_t *car = car;間違っています、私はあなたが「自己」を意味したと思います

于 2012-11-22T12:03:03.727 に答える