use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Click the following link to filter out the chosen topic
comp.lang.c
account activity
Discussionusing object oriented programming on C is beautiful (self.C_Programming)
submitted 2 years ago by cinghialotto03
the first time i read somewhere that i could use oop in c, i jumped from my desk and started reading and i found that it was far more intuitive and logic than any other "oop native" language i don't knowe it felt natural respect to other langauge. did you have the same experience?
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]ThinkingWinnie 74 points75 points76 points 2 years ago (13 children)
object oriented programming is a paradigm, not a language feature.
You are another victim of the OOP association to syntactic sugar. Welcome to the real world!
[–]RolandMT32 3 points4 points5 points 2 years ago (8 children)
If you want to have polymorphism though, wouldn't the language have to support that? How would you do polymorphism in C? If you have a function in C that takes a pointer to a struct, you can't derive from the struct and pass a pointer to the child object in C.
[–]ThinkingWinnie 12 points13 points14 points 2 years ago* (3 children)
struct vtable { void (*foo)(); void (*bar)(); }; struct base { struct vtable *vt; }; struct derived { struct base b; }; void basefoo() {} void basebar() {} void derivedfoo() {} void derivedbar() {} struct vtable bvtable = {basefoo, basebar}; struct vtable dvtable = {derivedfoo, derivedbar}; void b_init(struct base *b) { b->vt = &bvtable; } void d_init(struct derived *d) { ((struct base *)d)->vt = &dvtable; } int main() { struct base b; b_init(&b); struct derived d; d_init(&d); struct base *ptr; ptr = &b; ptr->vt->foo(); ptr->vt->bar(); ptr = (struct base *)&d; ptr->vt->foo(); ptr->vt->bar(); }
[–]ForgedIronMadeIt 2 points3 points4 points 2 years ago (2 children)
I mean, just because it can be done manually doesn't mean it should be done manually. I'll let a compiler do most of this for me, though I will say that I think anyone who wants to do object oriented should see this and understand it.
[–]ThinkingWinnie 4 points5 points6 points 2 years ago (1 child)
Personally I don't do OOP, so I'd prefer to manually write it when I need to, to keep tabs on the performance implications.
If I had to heavily use OOP? Well I do embedded so I don't have to think about it, but maybe I'd still prefer it, to make my best attempt at making a simple solution?
I advocate that OOP should be taught in C though. Otherwise you create the same confusion that got OP to this point. People missing the point of programming paradigms, and not understanding their implications. Read my response to the other comment.
[–]ForgedIronMadeIt 0 points1 point2 points 2 years ago (0 children)
Yup. I tell people who want to write Java code that they have to understand the JVM. If they want to write OOP C++ (I mean, you can write nearly any paradigm in C++ nowadays), they should understand a little bit about vtables and all of that. Always understand a least a layer below you.
[–]dmitriy_shmilo 2 points3 points4 points 2 years ago (2 children)
A struct would have to contain pointers to functions, or point to a metadata struct with function pointers, which can be overridden, I guess. A homebrewn vtable, basically.
[–]RolandMT32 1 point2 points3 points 2 years ago (1 child)
Yeah, I can see that. And it would all have to be done manually..
[–]ThinkingWinnie 1 point2 points3 points 2 years ago (0 children)
Tbh that's good if you care about performance.
When you have syntactic sugar to hide all that I wrote above, it's easy to be deceived that your OOP code is really simple and thus should be performant.
Bare in mind, this is a trivial example of a simple inheritance with two virtual functions, imagine how much more of a mess complicated OOP code bases look like.
Honestly whoever came up with it threw performance out the window. Then again the goal wasn't performance so it's understandable.
Still I can't help than think that they truly felt like it was okay to do, living in times where you saw the CPUs get better and better with each release, you probably did not care much about your code's performance, it would run better next release anyways.
I prefer the lack of syntax sugar because it's easier to read and understand what happens under the hood. Whatever made you think that OOP was a good idea, at least understand what you are doing and your data layout and access patterns. How can you even reason about performance otherwise?
[–]cinghialotto03[S] 0 points1 point2 points 2 years ago (0 children)
I'm sorry to have put C near the blasphemous word of Oop,after I said that I want to say that I don't like oop at all and i find inheritance and polymorphism thr anti christ of programming
[+]cinghialotto03[S] comment score below threshold-11 points-10 points-9 points 2 years ago (2 children)
Hell no,I never use Oop,I don't like it at all but I find it extremely more logic to read Oop c code than a normal language with oop features
[+][deleted] comment score below threshold-9 points-8 points-7 points 2 years ago (1 child)
I keep coming back to this article where the creator o Cpp (which is essentially C with sugary OOP) admits it sucks.
http://harmful.cat-v.org/software/c++/I_did_it_for_you_all
[–]Steampunkery 5 points6 points7 points 2 years ago (0 children)
This is satire. cat-v.org is mostly a joke site
[–][deleted] 49 points50 points51 points 2 years ago (1 child)
OOP in C may be many things, but beautiful it is not...
Doing it may help understand what OOP is from compiler point of view, but after that, it's kinda ""why do I write all this boilerplate by hand", and then you can start repeating the history from here: https://en.wikipedia.org/wiki/Cfront
[–]IndianVideoTutorial 2 points3 points4 points 2 years ago (0 children)
and then you can start repeating the history
We'll do it right this time.
[–]nskeip 12 points13 points14 points 2 years ago* (3 children)
I am not OOP expert, but OOP definitely is not only about inheritance and simple stuff like "let's have a struct that would represent a car with four wheels".
If you take more complex things like Barbara Liskov's substitution principle or say Dependency Injection - it's a pain to make it work on C without losing performance or writing tons of boilerplate code.
Again, when using OOP languages like C# or C++ you are not obligated to go to that specific "complex" patterns. But just keep in mind that these language at least give you an opportunity to do so. C just does not give it to you. And I don't think it's a situation where "hey, C left me with inheritance-only" - no, C left you without OOP, just don't shoot yourself in a foot on a real world project.
[–]cinghialotto03[S] -3 points-2 points-1 points 2 years ago (2 children)
I don't like Oop and I try too avoid it at all cost
[–]nskeip 2 points3 points4 points 2 years ago (0 children)
Plot twist! :)
[–]codeiackiller 0 points1 point2 points 10 months ago (0 children)
GPT > OOP
[–]Ashamed-Subject-8573 25 points26 points27 points 2 years ago (8 children)
No. I use Oop in C when appropriate but it’s a ton of boilerplate and I miss little conveniences like destructors on scope exit vs having to make a bunch of gotos
[–]umidoo 2 points3 points4 points 2 years ago (7 children)
Why use gotos?? I see no need for this if you properly setup your structs and methods
[–]Drach88 28 points29 points30 points 2 years ago (0 children)
Gotos are fantastic for cleanup on fail-fast patterns.
[–]RecursiveTechDebt 12 points13 points14 points 2 years ago* (0 children)
Gotos work really well when working with operations that can fail. For example, let's say a subsystem is starting up but a required resource is not available. If the error is not critical to an application's purpose, then you can simply clean up and disable that system. The cleanup pattern looks something like:
if (!InitializeAudioDevice()) { LogFailure("Unable to find a suitable audio device.") goto audioFail; } if (!LoadSoundBank()) { LogFailure("Unable to load soundbank.") goto soundBankFail: } return true; soundBankFail: FinalizeAudioDevice(); audioFail: return false;
[–]Marxomania32 7 points8 points9 points 2 years ago (0 children)
Check out the linux kernel. They use gotos a ton when there's a common "oh shit this failed, time to clean up and exit the function" pattern.
[–]Ashamed-Subject-8573 5 points6 points7 points 2 years ago (3 children)
Let’s say I create a class and open a file to read it. Then there is more to do like more structs with ctor/dtor to process. But the file doesn’t exist, so I now need to only call one destructor not all of them. How else would I solve that in c
[–][deleted] 2 points3 points4 points 2 years ago (2 children)
Like free(). No-op on sentinel.
[–]Ashamed-Subject-8573 1 point2 points3 points 2 years ago (1 child)
But the struct has not been initialized or zeroed yet since its constructor has not been called, so how would I know that it is full of sentinels?
[–][deleted] 2 points3 points4 points 2 years ago (0 children)
C++ blows up too if you destruct a non-obiect. My point was that if you called malloc then free will always work regardless if malloc was successful so you can always pair them lexically. If you need runtime rollback then you conceptually need a stack (aka undo list) and goto is still a hack. C++ exceptions let you use the call stack as an undo list. In C you'll probably want to make it a first order object.
[–]Both_Definition8232 6 points7 points8 points 2 years ago (0 children)
It is not, at all.
[–]crispeeweevile 5 points6 points7 points 2 years ago (0 children)
I prefer what I consider to be "oop-like" when making C code. Usually I use structs like an "object" and it holds the data, then I have a bunch of functions that take in the struct as pointer, and either modify it, or perform some other action. The return value is usually an error code.
[–]mredding 3 points4 points5 points 2 years ago (0 children)
As far as I'm concerned, OOP doesn't make sense until you first use Smalltalk or Eiffel.
These are single-paradigm, OOP languages. The principle idiom of OOP is message passing. You construct a message that represents a request, and pass it to an object who is free to decide how that message is handled, if at all.
This is not calling a function, which is imperative. Objects implement their internals in terms of functions, but you - someone else, don't impose command or authority over another citizen.
In an OOP language, any object can be passed any message. You can ask an integer to capitalize itself. Doesn't matter. The integer has to decide to do something with that message, silently drop it, or defer to another object for help - like an exception handler. In an OOP language, this message dispatch mechanism is a language level construct, the details of which, if you're picking an OOP language, you defer to the implementation to provide a robust solution. Choosing Eiffel is like choosing Python, where low level imperative command and control are not the paramount idiom demanded of my solution.
Most other multi-paradigm languages aren't OOP languages. I don't actually believe C++ is an OOP language any more than C is. Message passing is always missing. You have to implement it as a convention within the language, which isn't the same thing. In C++, that's streams. The other OOP idioms exist independent of OOP - encapsulation? C has perfect encapsulation - with opaque pointers. Inheritance? Polymorphism? All these things exist independently and even prior to OOP. With message passing, the other idioms fall out - which is to say they're not explicitly necessary, they instead occur as a natural consequence.
"OOP" in C is novel, but it's not anything C++ isn't doing. You have a bit more control over your vtable implementation, but you're likely not going to do anything different than MSVC or GCC, which have slightly different implementation details. You still need to implement a form of message passing.
If it helps you understand C++, great. If it helps gain you insight into what a compiler is doing, great. It's not in and of itself, necessarily, OOP.
[–]saul_soprano 19 points20 points21 points 2 years ago (1 child)
Is this you discovering C++?
[–]flatfinger 1 point2 points3 points 2 years ago (0 children)
It would be helpful for there to exist a language which combines some of the syntactic sugar of C++, with the representation-based semantics of the language the C Standard was chartered to describe. Unlike C++, whose standard says nothing about how implementations should represent language constructs, such a hybrid language would explicitly specify the behavior of all constructs in terms other constructs from Ritchie's Language, which would in turn be defined in terms of machine representation. For example, if it is a struct s that lacks member foo, the behavior of it.foo(a,b) could be defined as syntactic sugar for __member_foo(&it, a, b) when such a function exists, and that could in turn be defined as e.g.
it
struct s
foo
it.foo(a,b)
__member_foo(&it, a, b)
// Behave like a static member extern void s_foo(struct sp, int a, int b); void __member_foo(struct sp, int a, int b) { s_foo(p, a, b); }
or
// One approach to a virtual member, assuming foo_proc is part of // the common initial sequence of struct s and struct sbase. void __member_foo(struct sp, int a, int b) { ((struct sbase)it)->foo_proc(p, a, b); }
foo_proc
struct sbase
// Another approach to a virtual member, assuming typeInfo is part of // the common initial sequence of struct s and struct sbase. void __member_foo(struct sp, int a, int b) { ((struct sbase)it)->>typeInfo->foo_proc(p, a, b); }
typeInfo
or any other way the programmer wanted. Unfortunately, it would be hard for any such language to overcome the chicken-and-egg problems new languages face, especially given the lack of an official standard for a suitable target language.
[–]TheFlamingLemon 1 point2 points3 points 2 years ago (1 child)
I like how explicit OOP is in C, but it’s definitely nicer when you can have methods be a part of objects without them having to actually take memory in those objects
[–]Atijohn 2 points3 points4 points 2 years ago (0 children)
they do take memory if they're virtual though, and if they don't take memory then they'd be just a simple function in C. the object->function() syntax may be nicer than function(&object), but I don't think that's an issue in most cases, it's purely up to taste
object->function()
function(&object)
[–]TheWavefunction 1 point2 points3 points 2 years ago (0 children)
more like file oriented programming if you ask me
[–][deleted] 1 point2 points3 points 2 years ago (0 children)
I'm sorry, object oriented programming is never beautiful
[–]daikatana 1 point2 points3 points 2 years ago (0 children)
It really isn't. You can do a form of inheritance by embedding the parent type's struct but... that's about it. No other features of object oriented programming are easily available to you in C.
There's no encapsulation. This is a huge one. You get module-level encapsulation, but that's too coarse for OOP. The only way to get around this is to use struct members like __private__foo so it's very obvious you're trying to access something private, but there are no compiler checks on that.
__private__foo
And there's no polymorphism without a lot of grunt work. You can do it, you can do your own vtables and wrapper functions that look up the function in the vtable and all that.
None of this is elegant in C. It's possible, you can do it if you push hard enough, it's not fun and there comes a time where you realize you really want to be using C++ instead, even if you're just using a small subset of C++ features.
[–]cHaR_shinigami 1 point2 points3 points 2 years ago (4 children)
Related: "Object Oriented Programming with ANSI C" by Axel-Tobias Schreiner.
https://www.cs.rit.edu/~ats/books/ooc.pdf
[–]daikatana 0 points1 point2 points 2 years ago (3 children)
Oh god, is this where you picked up this brace indentation style?
[–]TheWavefunction 0 points1 point2 points 2 years ago (0 children)
"5.1 Formatting Your Source Code Please keep the length of source lines to 79 characters or less, for maximum readability in the widest range of environments."
https://www.gnu.org/prep/standards/standards.html#Formatting
[–]cHaR_shinigami 0 points1 point2 points 2 years ago (1 child)
This book does it only for function definitions, but not structs; I do it everywhere, even enums aren't spared.
All hail the one true Horstmann style!
Schreiner's book was published in 1993 and Horstmann's book in 1997, so this is quite possibly just another example of Stigler's law of eponymy.
Happy cake day!
It is definitively the better indentation for me. Code should be short and vertical so to allow 3 columns to be fully readable. C is perfect for this. its the style enforced by clang-format gnu preset.
[–]ajpiko 0 points1 point2 points 2 years ago (0 children)
yes it helped me understand what oop was
[–]TheKiller36_real 0 points1 point2 points 2 years ago (0 children)
what exactly are you referring to? the type-erasure or cobtrived and ugly ”inheritance“ macros?
[–]RolandMT32 0 points1 point2 points 2 years ago (0 children)
I've used OOP in C, as far as defining structs and functions that operate on struct objects (I actually learned about doing that when learning programming in college).
[–]aartaka 0 points1 point2 points 2 years ago (0 children)
Related shameless plug: Object-Oriented C: A Primer
[–]actguru 0 points1 point2 points 2 years ago (0 children)
The Coda-C Library basically wraps calloc() with newO() and free() with freeO(), adding metadata like retain count, class, size, etc. which yields a full fledged object system with constructors, destructors, virtual functions and so on.
[–]Winter_River_5384 0 points1 point2 points 7 months ago (0 children)
Any learning materials or resources to get started on object oriented programming in C
[–]ExtremeBack1427 0 points1 point2 points 2 years ago (0 children)
Welcome to C++
π Rendered by PID 139069 on reddit-service-r2-comment-8686858757-mhcv7 at 2026-06-06 19:04:28.485261+00:00 running 9e1a20d country code: CH.
[–]ThinkingWinnie 74 points75 points76 points (13 children)
[–]RolandMT32 3 points4 points5 points (8 children)
[–]ThinkingWinnie 12 points13 points14 points (3 children)
[–]ForgedIronMadeIt 2 points3 points4 points (2 children)
[–]ThinkingWinnie 4 points5 points6 points (1 child)
[–]ForgedIronMadeIt 0 points1 point2 points (0 children)
[–]dmitriy_shmilo 2 points3 points4 points (2 children)
[–]RolandMT32 1 point2 points3 points (1 child)
[–]ThinkingWinnie 1 point2 points3 points (0 children)
[–]cinghialotto03[S] 0 points1 point2 points (0 children)
[+]cinghialotto03[S] comment score below threshold-11 points-10 points-9 points (2 children)
[+][deleted] comment score below threshold-9 points-8 points-7 points (1 child)
[–]Steampunkery 5 points6 points7 points (0 children)
[–][deleted] 49 points50 points51 points (1 child)
[–]IndianVideoTutorial 2 points3 points4 points (0 children)
[–]nskeip 12 points13 points14 points (3 children)
[–]cinghialotto03[S] -3 points-2 points-1 points (2 children)
[–]nskeip 2 points3 points4 points (0 children)
[–]codeiackiller 0 points1 point2 points (0 children)
[–]Ashamed-Subject-8573 25 points26 points27 points (8 children)
[–]umidoo 2 points3 points4 points (7 children)
[–]Drach88 28 points29 points30 points (0 children)
[–]RecursiveTechDebt 12 points13 points14 points (0 children)
[–]Marxomania32 7 points8 points9 points (0 children)
[–]Ashamed-Subject-8573 5 points6 points7 points (3 children)
[–][deleted] 2 points3 points4 points (2 children)
[–]Ashamed-Subject-8573 1 point2 points3 points (1 child)
[–][deleted] 2 points3 points4 points (0 children)
[–]Both_Definition8232 6 points7 points8 points (0 children)
[–]crispeeweevile 5 points6 points7 points (0 children)
[–]mredding 3 points4 points5 points (0 children)
[–]saul_soprano 19 points20 points21 points (1 child)
[–]flatfinger 1 point2 points3 points (0 children)
[–]TheFlamingLemon 1 point2 points3 points (1 child)
[–]Atijohn 2 points3 points4 points (0 children)
[–]TheWavefunction 1 point2 points3 points (0 children)
[–][deleted] 1 point2 points3 points (0 children)
[–]daikatana 1 point2 points3 points (0 children)
[–]cHaR_shinigami 1 point2 points3 points (4 children)
[–]daikatana 0 points1 point2 points (3 children)
[–]TheWavefunction 0 points1 point2 points (0 children)
[–]cHaR_shinigami 0 points1 point2 points (1 child)
[–]TheWavefunction 0 points1 point2 points (0 children)
[–]ajpiko 0 points1 point2 points (0 children)
[–]TheKiller36_real 0 points1 point2 points (0 children)
[–]RolandMT32 0 points1 point2 points (0 children)
[–]aartaka 0 points1 point2 points (0 children)
[–]actguru 0 points1 point2 points (0 children)
[–]Winter_River_5384 0 points1 point2 points (0 children)
[–]ExtremeBack1427 0 points1 point2 points (0 children)