Hacker News new | ask | show | jobs
by eropple 4584 days ago
I'm not sure if it's game programming or C++ that makes him say what he's saying. I can't speak to his level of competence, but in writing my own game library (mostly for education, but also out of discomfort with tools like Unity) I have found myself ambivalent about visibility and find myself making a lot more stuff public than I otherwise would due to the (wonderful, why oh why don't more languages steal this) constness in C++. Constness can often replace private visibility for data--i.e., I don't need getters or setters. A field may be immutable once the object is instantiated, in which case I make it a const field, or it may be mutable, in which case the object's constness will handle it for me. (There's still the case where I need to perform transformations on a piece of data either on the get or the set, of course, and it's there that private usability is still of use.)

I came to C++ through a circuitous route and a lot of my early C++ is very Java- and Scala-influenced - private vars all over, getters, setters. I find my code becoming much more "public-first" as I get better at what I'm doing. That said, I'm uncomfortable with the idea of public being the default visibility; I think I do prefer to have to make that decision consciously while designing my APIs.

1 comments

Constness is a really useful concept especially since it has been extended to also mean thread-safe (at least in the standard library), but has a bunch of design flaws that make it very difficult to use correctly.

1. It is not the default. Everything should be const by default and should be marked mutable when necessary. This even seems to be consensus in the committee and has been done for newer language features (lambdas).

2. It is not "deep" when pointers are used. This one is actually inherited by C, but still is really painful. This is fixed in D.

3. const_cast is legal C++ in most circumstances (the only exception being an object declared const). This invalidates most assumptions optimizing compilers could possibly make and takes away a lot of usefulness because there is always someone that is going to const_cast stuff around.

4. It becomes very hard to use with polymorphic types, because const-ness is part of the function signature and affects override behavior. Can you really safely say something about const-ness and thread-safety of all classes you could possibly derive? I often find I cannot and when I really need runtime polymorphism I will usually end up with lots of const-less member function.

1. Agreed.

2. Agreed. I like D, or I want to anyway. Main problem is the garbage collector; I'm writing a game that I want to port to mobile and I don't really trust a garbage collector in a low-perf environment. Rust is sort of interesting for that reason but is a few years from being mature enough to consider I think.

3. Also agreed for projects in the large, but for the most part I write C++ for me (for an idea of the project size, my utility game library is ~14KLOC over about 200 compilation units, the game will probably be around half of both) is all my code and so I have certain assurances. The only one I'd be hurting is me. And I am averse to that. =)

4. This I'm not really so sure about. I have never really run into this issue - my base classes are generally close to all-virtual whenever possible and only expose a fairly limited set of methods. I have run into what you describe--the deepest nesting of polymorphism I have is my current project is in my drawing code, where a DrawSource is basically a time -> (rect, textureID) mapping and a Sprite is a timekeeper for DrawSource that performs a little matrix manipulation before invocation and has a list of child Sprites. I solved this by pulling everything I didn't need out of Sprite entirely and presenting a very simple interface. (I'm liberated a bit in that this is all my code, though, so I generally know what types I have bouncing around.)

In any case, I'll take flawed C++ const over "new ImmutableCollectionBecauseWeDontHaveConst<T>(someList)" when I can. I like Scala quite a bit but this mutable/immutable division drives me up the wall.