Home > Mobile >  How to achieve optimal inheritance-like with C struct?
How to achieve optimal inheritance-like with C struct?

Time:05-20

I come from an OPP background and have struggle with what is the optimal (speed wise) way of implementing what I need.

I define the below struct:

struct Vehicle {
    int A;
    int B;
}

And I want some other struct like:

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

In the end I have a function:

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

that takes an array of Vehicle as parameter and these can be either bike either car.

In f I need to access A,B and C if a bike or D if a car. How do I implement this?

For now I have done the below which works but I think is very inefficient and bad:

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

(NB: please no typedef, see: https://stackoverflow.com/a/4566358/19142731)

CodePudding user response:

It's mostly been said in the comments, but here's a workup of what's been said (and I have not used any typedefs, but personally I would).

So, point 1, use an enum for your vehicleType, and point 2, a vehicle can't be both a Car and a Bike so this is a good place to use a union to save space.

All of which leads us to something like this:

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;

And you might then do:

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

Most people (including myself!) would probably disagree with how I've (mis-) used upper and lower case here. Sorry, bit rushed.

CodePudding user response:

I would use C-style cast to pointer:

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
            }
    }
}
  • Related