1

As a learning experience I'm trying to achieve simple class inheritence in C, among other OOP features.

So far I've been able to properly hide "private" functions and attributes of a class from the outer context.

Let's consider Point as a simple class example. It is made up of three modules:

public.h

#ifndef POINT_PUBLIC_H_
#define POINT_PUBLIC_H_

typedef struct Point Point;

Point* newPoint(const int x, const int y);

int getX(const Point* self);

int getY(const Point* self);

void setX(Point* self, const int x);

void setY(Point* self, const int y);

void printPoint(const Point* self);

#endif

This is basically the public interface of Point and it also defines the type Point referring to a struct declared in another module, hiding its attributes.

protected.h

#ifndef POINT_PROTECTED_H_
#define POINT_PROTECTED_H_

struct Point {

    int x;
    int y;
};

#endif

It hosts the actual struct definition and it could also contain prototypes to functions meant to be accessible only by inhereting classes.

And then there's implementation.c which includes both public.h and protected.h and contains the actual code of public, protected and private functions.

This works great, but what if I wanted to define a Circle class, which extends Point?

I envisioned something like this:

#ifndef CIRCLE_PROTECTED_H_
#define CIRCLE_PROTECTED_H_

#include "../Point/protected.h"

struct Circle {

    Point parent;
    int radius;
};

#endif

Since the public functions of Point expect a pointer to Point, and since the first attribute of the Circle struct is a Point (not a pointer to it), given a Circle* c object, it becomes possible to do something like getX((Point*) c);. While this works fine, what I'm not happy about is that I can directly access the attributes to a Point object (including that one in the Circle struct of course) in the Circle modules. Moving the struct definition to the implementation module would make its attributes completely private, but then I wouldn't be able to directly istantiate a Point object in order to set up the mechanism of inheritence. Is there a way to make inheritence work while mantaining the privacy of the class that is being extended?

5
  • 4
    It is possible to use OOP concepts when programming in C, but this is where you reach the limits of it. For these details you should use a real OO language.
    – Ctx
    Commented Feb 12, 2020 at 18:13
  • I know about that. I'm not necessarily doing this because I plan to use these concepts in an actual program. As I said, this is just an experiment to learn something new. Of course, if what I'm asking really can't be done, I'm fine with this. But if there's someone who knows a different, more effective approach to this, I would be interested to learn about it :)
    – Gian
    Commented Feb 12, 2020 at 18:42
  • You could probably instantiate an opaque version of Point with a (large enough) character buffer, pass this around and cast this to the real Point structure in functions/source files, that may know the definition. But I would never do that in production code ;)
    – Ctx
    Commented Feb 12, 2020 at 18:47
  • 1
    Related: stackoverflow.com/questions/351733/… Commented Feb 12, 2020 at 18:55
  • I don't think hiding Point from Circle is a good idea (in C). You have a graphics source set and then there is user code. The graphics code should know all about the implementation of all shapes and operations; the user code can use void pointers. Commented Feb 12, 2020 at 19:48

1 Answer 1

0

Thanks to @RobertS supports Monica Cellio, I browsed the thread you linked for a little while and it actually gave me an idea.

I tried to actually split the struct in two parts, a protected part which is meant to be visible by the inhereting classes, and a private part which is completely invisible outside of the implementation.c module.

Here's what I did: in implementation.c I defined a new struct which contains all the private attributes:

struct hiddenPoint {

    int x;
    int y;
};

In protected.h I defined a type referring to this new struct, and I put a pointer to it in the actual Point struct

typedef struct hiddenPoint hiddenPoint;

struct Point {

    int aCircleCanSeeThis;
    hiddenPoint* hidden;
};

Since hidden is an opaque pointer, even when struct Point is visible some of its attributes can still be made inaccessible. This struct can of course host protected attributes as well, as demonstrated.

This is then my Circle struct:

struct Circle {

    Point parent;
    hiddenCircle* hidden;
};

It seems to work. Of course it complicates things a tiny bit (now it's p->hidden->x, instead of just p->x), but it does what I was looking for. Don't know if it's a good solution, maybe let me know! Also, if there are other approaches, I'd still like to hear about those :)

Not the answer you're looking for? Browse other questions tagged or ask your own question.