That was how I was doing OOP in C in the late 80s and early 90s. I found many of those concepts both in Python and in JavaScript. After all they were born around that time.
Python because of the insistence of declaring that explicit self argument, the pointer to the struct for the object.
JavaScript because of the prototype based OO. You can change the meaning of any field in an OO C struct if you know how to handle it later.
The webpage in the title is pretty good. It explains most things you need to achieve OOP in C. This PDF however pushes C for what it is not intended for, which leads to inefficient and obscure code.
For example, the first example in the PDF implements a Set. Everything is "void". This loses typing and will make code hard to read and maintain. The way inheritance is mimicked is hideous and inefficient. The PDF also heavily uses function pointers, which can be slow (because they aren't easily inlined) and waste memory (because each pointer costs 8 bytes on x64).
In all, most large C projects are doing OOP at some level. However, C is not C++ and is not intended for providing all OOP features like inheritance. This book should probably be titled "Wrong ways to OOP in C".
PS: The book does have some interesting ideas, but those are the "clever" things you will have to unlearn later. The author provides the source code for the book [1]. Have a look at the string implementation in Chapter Two. That is the most arcane and inefficient string implementation I have seen.
> However, C is not C++ and is not intended for providing all OOP features like inheritance.
There are parts of the ISO C standard specifically included to allow for inheritance. Consider:
typedef struct{
int x;
}struct_a;
typedef struct{
struct_a inherited;
int y;
}struct_b;
void function(struct_a *s)
{
s->x = 0;
}
Here struct_b inharates struct_a. You can call the function with either a pointer to struct_a or struct_b (either by casing or void pointer), because the standard specifically states that there can be no padding before the first member of a structure, so that the first member of a structure should have the same pointer as the structure itself. This part of the spec was written with the use case of inheritance in mind. (there is some people who don't read the spec that way, but this is the intention)
Sorry for being nitpicky... but that's pretty much what we do in the wg14....
Strict aliasing allows the compiler to elide the second a->x = 0. But if we use your inheritance scheme using casting of pointers, we could have a == b.
I wasn't too keen on this book. I read it hoping it would be more like the article in this post. But I felt it was more a case of someone re-inventing c++ with macros.
https://www.cs.rit.edu/~ats/books/ooc.pdf
(edit: link updated to point to author's website)