c - 在C语言编程中使用oop

标签 c oop

gcc (GCC) 4.7.2
c89

我正在练习在 C 中使用一些面向对象的风格。因为我想为我们的一些较大的项目这样做。

但是,在下面的代码中,我有一个父结构汽车和一个子 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;
}

最佳答案

在你的init_car

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

不应出现。您将构造行为与初始化混合在一起。在 C++ 中,构造函数负责完成这两件事;如果你想模拟相同的行为,你应该公开分配接口(interface)(例如,称之为construct),它将分配内存(你的malloc)并设置对象“方法” "到适当的函数)和初始化接口(interface)(它将执行初始化操作: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< 来调用它.

关于c - 在C语言编程中使用oop,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13511847/

相关文章:

javascript - 防止 TypeScript 公共(public)函数调用私有(private)函数

动态使用不同定义的 C 宏

c - UNIX下如何使用(C)将文件从一个文件夹传输到另一个文件夹?

c# - 面向对象编程基本概念(C#)

java - 仅比较两个实例之间的一个变量

.net - 有没有办法绕过 C#.NET 中的单类继承限制?

javascript - 在 Node.js 中扩展类的直接方法

c - 我在结构数组中使用冒泡排序时遇到错误,无法找到它

c - 如何初始化此功能?

c++ - std::cout 和 printf 数组