2

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?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
aganm
  • 1,245
  • 1
  • 11
  • 30
  • The only thing close to inheritance in C is using a common header on `struct`. – Barmar Mar 12 '20 at 04:58
  • 1
    But function pointers is the way to do what you're trying to do above. For instance, that's essentially how device drivers work in the Unix kernel, they're represented as objects with a bunch of function pointers for all the standard device operations. – Barmar Mar 12 '20 at 05:00

1 Answers1

0

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);
}
Pratik Sampat
  • 330
  • 1
  • 12