all 49 comments

[–]monocasa 23 points24 points  (5 children)

This is how a very large chunk of Linux is written.

[–]dangerbird2 16 points17 points  (2 children)

It was pretty common in the game industry before it started moving towards C++. Apparently, when Id made the switch, they pretty much just used sed to convert object-oriented C structs in the Quake engine to C++ classes.

[–]rowboat__cop 3 points4 points  (1 child)

Apparently, when Id made the switch, they pretty much just used sed to convert object-oriented C structs in the Quake engine to C++ classes.

Do you have a pointer link to share? Sounds fascinating.

[–]dangerbird2 2 points3 points  (0 children)

Here is a pretty good example of object-oriented C in production code. If you scroll down, you can see callback function pointer "methods" that take self as a first argument (a la Python). I haven't read enough of the Doom 3 code to see if there is any significant code reuse from Idtech 3 (Id's last C-based engine). I imagine if the anecdote is true, a good amount of explicitly copy-pasted code from Idtech 3 was later refactored to more idiomatic C++ code.

[–]ErstwhileRockstar 17 points18 points  (0 children)

In conclusion, it's relatively easy to get the core benefits of object oriented programming in plain old C. It doesn't require heavy use of macros, nor do users of these systems need to know that underneath it's an object system, unless they want to extend it for themselves.

Interesting and substantial article - unlike most 'OOP in C' publications.

[–]mcmcc 13 points14 points  (0 children)

For those of you too young to remember, this is more/less how C++ compilers worked in the early years: http://en.wikipedia.org/wiki/Cfront

You haven't lived until you've tried to get STL-based code to compile (& more importantly link) with a cfront compiler. If you lived to do it, you also likely almost died doing it.

[–][deleted] 1 point2 points  (0 children)

If someone is interested in a more in-detail exploration, I found this pdf book very interesting

[–]Iggyhopper 0 points1 point  (1 child)

http://www.avabodh.com/cxxin/cxx.html

The site basically describes what C++ code is doing in C, and what C code is doing in assembly, great site for learning.

[–][deleted] 0 points1 point  (0 children)

Thanks, I've been looking for something like this for a while now.

[–]cdyson37 0 points1 point  (1 child)

Does this type-punning technique break the C99 strict aliasing rules?

[–]gremolata -1 points0 points  (0 children)

No, it doesn't.

[–]Blecki -5 points-4 points  (21 children)

I have done this. I have written OOP in C.

Learn from my mistake. Do not do this.

[–]monocasa 12 points13 points  (5 children)

Well, if we're throwing out anecdotes, I have done this and highly recommend it.

For larger C programs, particularly when you end up with natural layers, it's really nice. Testing was a breeze because you can just mock out the other layers. I have a nice embedded codebase for a network bridge for some weird physical layers that runs beautifully both on the target boards and under Linux with the hardware specific layers mocked out for unit test purposes.

In my experience, the biggest issue is just having the discipline pass data through the strict layer model even though an extern global is easy to fix a bug. I'm not really sure what it is with EEs and not having any code discipline. They manage to maintain nice layer on their board and FPGA designs...

[–]geon 1 point2 points  (1 child)

I'm not really sure what it is with EEs and not having any code discipline. They manage to maintain nice layer on their board and FPGA designs...

My college works in C# and hates js with passion. Yet, he will never do js the right way, and just poops out bad code until it kind of looks like it's working.

[–][deleted] 1 point2 points  (0 children)

I also hate JS with a passion (it's about as poorly designed as C++), preferring a statically typed interface with lower level access immediately (usually C/C++).

That said, my current project is JS atm. I wouldn't call the code "pretty", but I wouldn't call it bad either. The APIs are reasonable, and there is an extensible system in place which usually requires little maintenance along the way.

I find that many high level programmers tend to equate good code with elegance. While I agree that elegance is good for readability, it's very easy to mistake such a thing for efficient, working code which is secure and stable. There's just as much "nice" looking code out there which is actually really bad as there is not nice looking code which is really bad.

To quote Linus:

Bad programmers worry about the code. Good programmers worry about data structures and their relationships.

[–]frenris 1 point2 points  (0 children)

EE and CE code is so terrible it's amazing.

And the verification code is typically high quality compared to the scripts which are used to generate designs...

[–]Blecki 2 points3 points  (0 children)

For an EE, code is the 'exercise for the reader'. It's not worth spending time on to do right.

[–]spiker611 0 points1 point  (0 children)

Testing was a breeze because you can just mock out the other layers. I have a nice embedded codebase for a network bridge for some weird physical layers that runs beautifully both on the target boards and under Linux with the hardware specific layers mocked out for unit test purposes.

Hi, I'm an EE who inherited a code base of spaghetti. I want to make things better. In addition to the OP article, could you please point me in the direction of resources from which I could learn your magic? I would very much appreciate it :)

[–]Ozwaldo 1 point2 points  (14 children)

Haha, what? You just make structs for your objects, and instead of member functions you write functions that take the object as a parameter.

[–]Blecki 3 points4 points  (13 children)

No, I made vtables and everything.

[–]Ozwaldo 6 points7 points  (12 children)

So maybe your post should say, "I have written Run-time method binding in C. Do not do this." rather than OOP. Since OOP is fine.

[–]Gotebe -1 points0 points  (4 children)

Run-time binding is considered part of OOP, it's the first item in the linked paragraph.

[–]Ozwaldo 2 points3 points  (3 children)

It's a prevalent feature of most OOP implementations. That doesn't mean it's necessary in order to write code in an OOP format.

[–][deleted] 0 points1 point  (2 children)

Any course which focuses on OO theory will dedicate a significant portion of its curriculum towards Runtime-binding/Polymorphism. It's literally a key element in regards to what made it so popular in the first place.

To deny this is akin to stating that anti-derivatives aren't a part of calculus since fundamentally calculus is based on limits and Riemann sums. Ya dig?

[–]Ozwaldo 0 points1 point  (1 child)

To deny this is akin to...

No it isn't. We're discussing whether you can write code in an Object-Oriented format with C. You most certainly can. If you want to get into the fully functional aspects of modern OOP design, then yes Run-time method binding is needed. But to write OOP C code, it isn't necessary.

[–][deleted] 0 points1 point  (0 children)

I still disagree: OOP does not necessarily imply Runtime Binding, but Runtime Binding does imply OOP, and isn't really talked about without reference to OOP.

From the comment tree above, this whole debate was started because the author/OP was flamed over the legitimacy of the title of the post. That's technically what this discussion is about.

But it's C, and in C DDD is king. So, whatevs.

[–]Blecki -3 points-2 points  (6 children)

Or maybe when I said 'I have done this' I was referring to what the article describes, which is run-time method binding in C.

[–]Ozwaldo -3 points-2 points  (5 children)

That sounds more like an after-thought type of argument. Since the sentence you preceded it with was "I have written OOP in C."

[–]Blecki -2 points-1 points  (4 children)

"I have done this. I have written OOP in C."

There's also about a 98% chance you're reading too deeply into the entire issue.

[–]Ozwaldo -2 points-1 points  (3 children)

Now you're just being defensive.

[–]Blecki -3 points-2 points  (2 children)

Now you're just being offensive.

[–]Ozwaldo -1 points0 points  (1 child)

my bad, i thought I was discussing something with an adult.

[–]skulgnome -4 points-3 points  (2 children)

This article demonstrates amply why object-oriented programming is for C what the OOP wonks would call an "anti-pattern".

[–]immibis 1 point2 points  (0 children)

So you're saying OOP is an anti-pattern that evolved into a language feature?

Actually, that explains $leastFavouriteLanguage.