"Class" is the worst C++ keyword
nguillemot.blogspot.ca
nguillemot.blogspot.ca
But this is a losing battle. "class" conveys intent to C++ programmers. There are lots of things that are needlessly complex in spoken languages (like do inanimate objects really need to be masculine or feminine?), but you can't just start speaking differently when the existing meaning is burned into people's brains.
As an example of existing convention, take the Google C++ Style Guide: http://google-styleguide.googlecode.com/svn/trunk/cppguide.x...
Use a struct only for passive objects that carry data;
everything else is a class.
The struct and class keywords behave almost identically
in C++. We add our own semantic meanings to each
keyword, so you should use the appropriate keyword for
the data-type you're defining.Personally I think the mistake was in making them the same. In Ides, a friend's LLVM-based PL (no contributions here, just some discussion and ideas), an instantiated 'struct' is a non-polymorphic object rather like in C#; this allows for more expressive code by logically attaching methods to the struct but without creating a vtable and breaking C compatibility.
C++ doesn't come from the web era, where you can push code filled with bugs and fix them over time in a process that's seamless and invisible to the user. C++ comes from a time when software couldn't be changed once it was shipped, and so it was more important to strive for integrity over raw ease of coding.
Although I still don't see the argument for today's coding, as maintenance is the primary cost of web applications.
This argument is so backwards. Having a garbage collector or a VM that ensures memory access safety, now that's what contributes to less bugs. Enforcing the freaking default visibility of class members to be private, does not. If you try to make this argument, which defies common sense, then show me some numbers.
And btw, good API design is not measured in the number of public members you have on a class.
Sarcasm aside: having more experience with C than C++, I find my C++ code rather significantly more resistant to buffer overflows, off-by-one errors, etc; it's when I'm interfacing with primarily C-based APIs that force me to do pointer math and so forth that I hurt myself. I don't have the confidence to write in C (fairly) quickly and correctly as opposed to C++. In this way C++ does come from that earlier era that the grandparent poster referred to: where Java didn't exist yet and the managed options weren't particularly fast, but C++ (even in its nascent form) could help you provide yourself tools for encouraging correctness that C could not.
Today, it's a different story. The STL (particularly as of C++11) is advanced to the point where it's very possible to write code that is, relative to Java or other managed languages, generally very fast and definitely very portable, while retaining pretty solid guarantees of safety. And I either I or the compiler are more likely to either notice my mistakes, which I inevitably make, in C++ than C.
I actually only very rarely use smart pointers in my main C++ project; my game has a simple lifecycle and wouldn't benefit from them much, though I could probably stand to use unique_ptr more than I do. The primary place I use them is to use std::auto_ptr to clean up after myself when dealing with try-catch blocks--I standardized on them before really understanding unique_ptr and my use of them is single-function-limited so I kept it consistent. The game itself is modeled on a stack-based state machine and I'm able to pretty easily reason about my object lifetimes within each state without smart pointers.
In your attack on my comment, you're starting to argue against something I'm not talking about or implying.
Good abstractions and code structure are created in a large part by being very careful about what's public. Defaulting to public helps a programming process that tends to ignore abstraction and structure, leading to heavy maintenance costs later. There's really no argument here, this is best practices established decades ago. It's fine to challenge establishments with new findings, but I find this article and your comments completely brain dead and unproductive because you're just lacking understanding of core principles.
class Foo {
public:
stuff;
private:
other stuff;
};
What's the point of private-by-default if everybody overrides it anyways?It's not a bug, it's a feature. The idea is, you should always prefer private to protected and protected to public (by transitivity, private > public). This is good practice which helps build compact interfaces and maintain encapsulation.
Another reason to use "class" is because it's OOP terminology. There's no notion of "struct" in OOP (in fact, structs shouldn't even be there, they're an atavism).
It's well known that protected is not any safer than public. Anybody can inherit and use it.
You can still make members private in structs. It's only less redundant:
class X { public: stuff; private: other stuff; };
vs struct X { stuff; private: other stuff; };
> Another reason to use "class" is because it's OOP terminology. There's no notion of "struct" in OOPThat's cargo cult programming. Using "class" doesn't make your code OO. The language we are programming in is C++, not OOP.
I shall proceed apace now to call
var x = 5;
(function() { return x + 2; })();
a glarfblork instead of a lambda, then, if semantics of naming should just be pitched out a window.Ok for a minute lets consider what this "more" code is. It is simply: "public:" when you want to start specifying the public members. You can even do this at the very start if you want ALL members to be public.
Now lets compare this to java or C# where (to the best of my knowledge), there isn't the ability to say "from here on, all members are private/public" and thus you have to give access specifier with EVERY member.
So the author can't be bothered to write "public:" once, but is ok writing public with EVERY member? Now THAT is absurd.
Is it a functor? Is it a data structure? Do I need C-compatibility? Do I want to encapsulate behaviour and validate correctness? Do I want to maintain the company style?
Ah, and you found a gap in the template usage. Something not well thought. Some little case that the standard falls for it. Join the line, son. You got to understand and accept this. If you do you have a wonderful toolbox to architect whatever you want with it. If you don't you are another guy on the internet shouting that "C++ sucks".
Again, the analysis is interesting, but it misses the real deal when trying to make a point. Guy named Robert in the comment section does hit the nail by the head by the way. The real point is that structs are raw data structures while classes are fully featured OOP entities. Don't put they in the same box.
That's not true. Structs and classes are identical except for the minor functional differences highlighted in the article.
By convention? Nope. The term struct pretty much stands for a pure data construct. C++ attempted (and pretty much failed) to make this distinction. Some languages, like C#, did a much better job.
In the real world we are always urging to being consistent. While other languages do a pretty good job by enforcing it, on C++ this is more on your shoulders.
These days, I prefer to create an interface using the PIMPL idiom [2] completely hiding the underlying implementation, whilst the implementation itself preferably consists of data structures and collections of these (hence 'struct') and some templated functions to modify these. This also resonates with an old C mantra: design data structures first, model functions after their behaviour or something similar [where I just cannot find a quote for].
My main gripe with using 'struct' in favor of 'class' is probably the compatibility problem with other programmers that might become confused as to why you are doing such weird things...
Wrong.
struct Foo;
class Foo {
};
int main(int, char**) {
Foo f;
}
compiles cleanly with -ansi -pedantic -Wall -Wextra besides warning about unused variable.http://cboard.cprogramming.com/cplusplus-programming/134827-...
You want to make a part of a struct private?
/* private */
Need a stronger deterrent? /* private, don't touch */
Need to protect against random people? Sure, only then - private:
But if you are working in the confines of a smaller team of people who read comments and generally abide by coding conventions that aren't enforced in the code, then it works beautifully and results in a slender and more readable code.Thought this was a joke first, but it's not? Is it possible you have worked in the same place or with the same people a long time? I just can't imagine this would work for us.
And I thought about it quite some time, but I really cannot see why you would prefer a comment (ie ignored by compiler, same keyword but surrounded with a few extra keystrokes) by a true first citizen keyword that does the same and enforces it? That would be the same as comments saying "hey this is const" instead of using proper const-correctness, no?
And, yes, it surely stops them better than some flimsy member access restrictions.
/* SHARED BETWEEN THREADS! careful. */
I'm sure people will read it. And then write safe, reliable code.
I tweaked private members from outside the class.
I never regretted it.
There's probably a moral here, but I'm not sure what it is.
;)
#define private public
(!)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. 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.
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.
Not all committee's are bad and not everything they produce are bad. The C++ steering committee is made up of dedicated and sharp people...There are, at the very least, good reasons for most of their decisions.
You may not know the whole story just from your experience.
I'm just saying...
Edit: I didn’t mean to dismiss the article; I meant to dismiss C++. It’s unsurprising to C++ users that the language is complex; we should choose our battles carefully. Why complain about “class”, which is a relatively innocuous design bug, when other issues are so much more pressing? How do we balance immutable objects against move semantics? How do we relax constraints in the standard library for improved performance, while also enforcing constraints for correctness and safety? How do we migrate away from C++ when there are no viable alternatives?
1. Templates
2. Template-based standard library
3. Lambda expressions
4. std::bind
all of which make C++ much more expressive than C.
In terms of performance "power", there's almost no difference. Sure, calling a virtual method is slower than calling a function in C, but you don't have to "pay" for it with performance if you don't use it.
EDIT: god-dang formatting
I want a language like C, one that interfaces well with C, but with memory safety, static polymorphism, real vector types (to avoid the aliasing problem), and real higher-order functions, all with minimal runtime overhead. So I’m building one (Kitten). Mozilla (Rust) and several others (Nimrod) have similar ideas.