Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

C vs C++ vs Something Else

Name: Anonymous 2010-04-07 17:09

Hi folks,

After getting frustrated that I couldn't easily accomplish what I wanted to in C, such as growable type-safe arrays and inheritance/polymorphism, I recently partially converted my ~10ksloc game project to C++. I didn't convert it all at once; I just made it all compile as C++, and gradually converted it as I worked on new stuff. About half of it is OOP/templates, and the other half is still pure C99 which compiles as C++. Notice I said 'easily'; I did write a type-safe vector template as a macro which you explicitly instantiate, and I did have a reasonably complex inheritance tree by writing vtables manually. These were just a pain in the ass to maintain.

Now I am somewhat regretting this decision. I'm realizing that these things that pushed me to convert it to C++, I shouldn't really have been doing them in the first place. Growable vectors (such as std::vector) are a terrible idea. Dynamic memory allocation is just a bad idea in general. You can't use these because an allocation might fail at any moment. Whether you throw an exception or you correctly handle and propagate a memory error via return values, it doesn't matter; you can't usefully recover in the middle of an operation. The only sane way is to pre-allocate everything you need at load time. If you do this properly, growable vectors are useless.

And complex inheritance trees are just bad. I should instead have been doing pure polymorphism, without inheritance. There's still a bit of overhead in writing a vtable, but there's no complexity. I spent so much time figuring out what methods go in which object, and shuffling them around from base classes to subclasses and back again... I should have learned to separate my algorithms from the objects they apply to.

I'm also finding that all the supposed advantages of C++ are useless or inferior to C. C++ encapsulation and header file management is even worse than C, because I have to expose my structure and private methods causing endless rebuild cycles. Creating callbacks is WAY more complicated than it should be (have to define an interface and then implement it instead of just handing over a function and struct pointer.) What is the point of all this?

The only feature I see myself using right now that isn't completely useless is overloading on types. Namespacing all my functions manually is a pain, and the argument that it helps readability doesn't really fly.

Lately I've been contemplating creating my own toy language, which is basically C except it doesn't use header files and allows overloading on types. There are tons of quicky compiler tutorials out there using tools like Flex+Bison; I am sure I could create a C99 parser which additionally allows overloading on argument types, and simply outputs C99 with header files and fully namespaced functions (or just calls LLVM directly).

Ironically this sounds a lot like Go, except I find Go has made a whole lot of bad decisions: garbage collection is a horrible idea for a systems/game language, enforcing encapsulation / exporting functions via naming conventions (uppercase wtf??), whitespace is starting to matter (notice what they're doing with removing semicolons, and all the bullshit wierdo special cases, like where you have to leave an extra trailing comma if you break up your argument list in different lines).

Would a language like this interest anyone? Should I just keep my project the way it is, half C++ and half C? What to do?

Name: Anonymous 2010-04-07 18:03

Dynamic memory allocation is just a bad idea in general. You can't use these because an allocation might fail at any moment. Whether you throw an exception or you correctly handle and propagate a memory error via return values, it doesn't matter; you can't usefully recover in the middle of an operation.

How often does that happen to you? And how exactly does your game project is supposed "meaningfully recover" from the OOM?

I did have a reasonably complex inheritance tree by writing vtables manually.

Ah, I see. Let me guess, your game has not yet gone beyond the stage of drawing a rectangle on the screen, maybe even a moving one.

You are not a programmer yet, man. The necessary quality of a programmer is the ability to see what is important and what is not. Churning out clever code does not a programmer make, the code is worth anything only if it solves a real problem.

Recovering from OOM is not important, you are writing a goddamn game. Hand-optimizing vtables and doing other crazy shit is not important, because it is not a bottleneck.

I too went through that phase when I invented complex, generalized frameworks solving nonexistent problems. Yeah, endlessly shuffling methods around trying to make the API nice and easy to use without ever actually using it is one of the most distinct hallmarks of this phase.

The cure is: stop this bullshit immediately. Write something that works passably, call it a prototype and start writing the actual code solving the actual problems. Then you'll see what the real requirements for the underlying code are. Even experienced programmers can't predict this stuff in advance -- and what makes an experienced programmer is that he is aware of that and doesn't try too hard, preferring to leave the code as flexible as possible. Clarification: by "flexible" I mean simple, small, easy to throw away and rewrite from scratch, because any other clever way of achieving "flexibility" would fail. And you are not even a programmer yet, let alone experienced.

Go and write the damn game. Then look back and woe the time you wasted so uselessly before.

Would a language like this interest anyone?
No. You have to be a programmer before you design a programming language, no one could be interested in a music editing program written by a deaf person.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List