Convert C++ OO hierarchy to C procedural

Viewed 78

I have been using C for a while yet sometimes when I think of how to solve a problem, I can't seem to think of any other way but in a OO way, as I was taught in school. And as I have been using C, I mostly have been using OO patterns but in C, sometimes fighting against the language to make it work. To go with a simple example, If I need to write a file system resource abstraction, I'll be thinking of writing a Resource base class, which will be inherited by an ImageFile class and by a AudioFile class, for example.

class Resource {
    bool opened;
    virtual bool load_file(const char *fpath);
    virtual bool release(void);
}

class ImageFile : Resource {
    bool load_file(const char *fpath) { ... }
    bool release(const char *fpath) { ... }
}

class AudioFile : Resource {
    bool load_file(const char *fpath) { ... }
    bool release(const char *fpath) { ... }
}

int main() {
    Resource img = ImageFile();
    Resource mus = AudioFile();

    img.load_file("my_image.png");
    mus.load_file("song.mp3");

    img.release();
    mus.release();

    return 0;
}

In C, I replicate this behaviour using function pointers. Thing is, that's still OO design, and I want to learn to think procedural. How would you go designing this same problem in a procedural way? How does OO inheritance translate to procedural? How do you think procedural?

1 Answers

Your idea leading to function pointers is definitely the right way to go.

The idea is that we have function pointers the "parent" class, the child class bears a pointer to that parent structure and we when we define our own definition of the functions we can point those functions to our implemented ones.

I'll rough out a simple example for you on how that can be achieved.

struct resource {
    bool (*load_file)(const char *fpath);
    bool (*release)(const char *fpath)
};

struct imageFile {
    struct resource *ops;
};

struct audioFile {
    struct resource *ops;
};

bool image_load_file(const char *fpath) {...}
bool image_release(const char *fpath) {...}

bool audio_load_file(const char *fpath) {...}
bool audio_release(const char *fpath) {...}

int main () {
    static const struct op1 = {
        image_load_file,
        image_release,
    };

    static const struct op2 = {
        audio_load_file,
        audio_release,
    };

    // Assigning the functon pointers

    struct imageFile *im = malloc(sizeof(*im));
    im->ops = op1;

    struct audioFile *aud = malloc(sizeof(*aud));
    aud->ops = op2;

    // Calling the functions
    im->ops->load_file(fpath);
    im->ops->release(fpath);
}
Related