如何使用 C 结构实现最佳继承?

How to achieve optimal inheritance-like with C struct?

我有 OOP 背景,一直在努力寻找实现我需要的最佳(速度)方式。

我定义了以下结构:

struct Vehicle {
    int A;
    int B;
}

我想要一些其他结构,例如:

// is Vehicle
struct Bike {
    int C;
}
// is Vehicle
struct Car {
    int D;
}

最后我有一个函数:

void f(struct Vehicle vehicles[], int nVehicles) {
    for(int i=0;i<nVehicles;++i){
        struct Vehicle v = vehicles[i];
        //if v is a car do something
        //else if a bike do something else
    }
}

Vehicle 数组作为参数,这些可以是 bikecar

f 中,我需要访问 ABC(如果是 bikeD(如果是汽车)。 我该如何实施?

现在我已经完成了下面的工作,但我认为这是非常低效和糟糕的:

struct Bike {
    int A;
    int B;
    int C;
}

struct Car {
    int A;
    int B;
    int D;
}

struct Vehicle {
    char* vehicleType;
    struct Bike;
    struct Car;
}
void f(struct Vehicle vehicles[], int nVehicles) {
    for(int i=0;i<nVehicles;++i){
        struct Vehicle v = vehicles[i];
        char *vehicleType = v.vechicleType
        if(strcmp(vehicleType, "Bike")==0) {
            // Do something
        } else if(strcmp(vehicleType, "Car")==0) {
            // Do something else
        }
    }
}

请注意,我只定义了一次结构,从未修改过它们的属性,我只是在阅读它们。

我会使用 C-style 转换为指针:

struct Bike {
    int A;
    int B;
    int C;
};

struct Car {
    int A;
    int B;
    int D;
};

struct Vehicle {
    const char* vehicleType;
};

void f(struct Vehicle vehicles[], int nVehicles) {
    for (int i = 0; i < nVehicles; ++i) {
        Vehicle v = vehicles[i];
        const char* vehicleType = v.vehicleType;
            if (strcmp(vehicleType, "Bike") == 0) {
                Bike* b = (Bike*)&v;
                //Do what you need with 'Bike' now
                b->A = 1; //For example
                b->B = 1; //For example
                b->C = 1; //For example
            }
            else if (strcmp(vehicleType, "Car") == 0) {
                Car* c = (Car*)&v;
                //Do what you need with 'Car' now
                c->D = 2; //For example
            }
    }
}

大部分都是在评论中说的,但这里是对所说内容的处理(我没有使用任何 typedef,但我个人会)。

因此,第 1 点,为 vehicleType 使用 enum,第 2 点,vehicle 不能既是 Car 又是 Bike 所以这是使用 union 保存 space 的好地方。

所有这些都将我们引向了这样的结果:

enum VEHICLE_TYPE { bike, car };

struct Vehicle
{
    enum VEHICLE_TYPE vehicleType;
    union u 
    {
        struct Bike
        {
            int top_speed;
        } Bike;

        struct Car
        {
            int number_of_seats;
        } Car;
    } u;
} Vehicle;

然后你可能会这样做:

int main ()
{
    struct Vehicle v;
    v.vehicleType = bike;
    v.u.Bike.top_speed = 100;
    ...
}

大多数人(包括我自己!)可能不同意我在这里(错误地)使用大写和小写的方式。对不起,有点仓促。

对于 C 结构继承,我体验最多的基本模式如下:

struct Vehicle {
    int A;
    int B;
};

struct Bike {
    struct Vehicle;
    int C;
};

struct Car {
    struct Vehicle;
    int D;
};

只要 Vehicle 发生变化,子 class 就会自动获得这些变化。

对于内省部分,最常见的是一个特定的字段,正如其他人所指出的以及在 Objective-C 中实现的那样。这个想法是在层次结构的顶部 class 定义该字段:

struct Object{
    int whatami;
};
struct Vehicle {
    struct Object;
    int A;
    int B;
};

可能对软件工程 Stackexchange 上的一些相关问题感兴趣: