Earlier quoted context omitted.
please post an example of what such a callback would look like
Linux kernel code makes heavy use of object-oriented design patterns [0]. It's not the best of its kind, but still provides a reasonable example of how OOP can be achieved in C: https://gist.github.com/cakturk/cd75d0ca588151c86d641cb6d5a1... [0] https://lwn.net/Articles/444910/
OOP in C
61–70 of 149 posts
Re: OOP in C
#62I have not looked through the source myself but thought this might be an interesting reference.
Re: OOP in C
#63Earlier quoted context omitted.
Polymorphism in C is trivial: You use a vtable - a struct of method pointers. Same approach most languages with "simple" method resolution mechanisms, like e.g C++, uses under the hood. You don't need macros. You either call via the vtable, or you write a wrapper per interface per message. E.g. struct class { void (*vtable[NUM_SLOTS]); }; struct object { struct class * class; }; typedef struct object object; const in…
what does an "object" look like? how do i derive from it?
Re: OOP in C
#64Strongswan, the open source IPSec VPN software ( https://www.strongswan.org/ ) is written in object oriented C. Ref: https://docs.strongswan.org/docs/5.9/devs/objectOrientedC.ht... I have not looked through the source myself but thought this might be an interesting reference.
This is relatively common in software with a modular architecture that is intended to run on embedded systems and whose design dates back from a time when C++ standard library was not really well supported on such systems. This is also useful when performance is highly important and you can't afford the C++ vtable overhead.
Re: OOP in C
#65Earlier quoted context omitted.
That wouldn't actually help much. In the case that there is no inheritance, using a function pointer has unnecessary overhead (pointer storage, indirect call, additional parameter). In the case of inheritance, the pointer type differs and thus the function pointer type wouldn't be compatible either.
Inheritance is nowadays almost considered a bad practice, in fact newer languages, such as Rust, doesn't support it, and in languages that has it (Java, C#, etc) nowadays they always tell you to prefer composition over inheritance. > using a function pointer has unnecessary overhead This is true, it's inefficient. But for a lot of application, also irrelevant at performance level, and would provide a good abstraction…
It got a bad reputation because it was abused. Bad practice is using inheritance when a tuple or a map would suffice.
Re: OOP in C
#66I see so many uses of the term ADT that I can't really give anyone a confident definition
Using ADT to mean “abstract data type” does not mean anything more than what most people mean when they say “type”. Outside of distinguishing from other meanings of the word “type” there is no practical reason to ever say it. It doesn’t sound fancy, it just sounds like getting high on your own supply of acronyms. It is not an important term to learn as a beginner in the first chapters of a programming book. We should…
Abstract data type is a type where you don't get direct access to the information contained in it. The encapsulation is what makes it "abstract".
Re: OOP in C
#67I see so many uses of the term ADT that I can't really give anyone a confident definition
Using ADT to mean “abstract data type” does not mean anything more than what most people mean when they say “type”. Outside of distinguishing from other meanings of the word “type” there is no practical reason to ever say it. It doesn’t sound fancy, it just sounds like getting high on your own supply of acronyms. It is not an important term to learn as a beginner in the first chapters of a programming book. We should…
Re: OOP in C
#68Earlier quoted context omitted.
Inheritance is nowadays almost considered a bad practice, in fact newer languages, such as Rust, doesn't support it, and in languages that has it (Java, C#, etc) nowadays they always tell you to prefer composition over inheritance. > using a function pointer has unnecessary overhead This is true, it's inefficient. But for a lot of application, also irrelevant at performance level, and would provide a good abstraction…
Inheritance is the best solution to some problems. It got a bad reputation because it was abused. Bad practice is using inheritance when a tuple or a map would suffice.
Inheritance (from implementation, I've nothing against implementation of interfaces or inheritance from abstract base classes) has a ton of problems, more importantly the fact that it makes the code more difficult to understand and to evolve.
Composition on the other hand is something more natural, even if we think about real life: you don't usually take an object and "extend" it, you take multiple object and use them together to build something!
Re: OOP in C
#69A whole book on this topic was already written in 1993 by Axel-Tobias Schreiner. It seems to be freely available nowadays: https://www.cs.rit.edu/~ats/books/ooc.pdf (edit: link updated to point to author's website)
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.
Re: OOP in C
#70Earlier quoted context omitted.
Inheritance is nowadays almost considered a bad practice, in fact newer languages, such as Rust, doesn't support it, and in languages that has it (Java, C#, etc) nowadays they always tell you to prefer composition over inheritance. > using a function pointer has unnecessary overhead This is true, it's inefficient. But for a lot of application, also irrelevant at performance level, and would provide a good abstraction…
Rust has a flavor of inheritance through Traits and #derive.
Traits are like interfaces in OOP languages (simplified), the equivalent of a class would be a struct + all the impls of that struct. And that thing cannot be extends, a struct is fixed when defined and nobody can extend it, you can use composition that is the correct to me way to go.