
"Class" is the worst C++ keyword - DmitryNovikov
http://nguillemot.blogspot.ca/2013/11/class-is-worst-c-keyword.html
======
haberman
I enjoyed this article; I learned several things (I didn't even know that
"struct Employee : Person {" was valid syntax) and I can't argue with any of
the factual content.

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...](http://google-
styleguide.googlecode.com/svn/trunk/cppguide.xml#Structs_vs._Classes)

    
    
        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.

~~~
eropple
Agreed. In the literal sense they are very much two keywords for the same
concept, but culturally, a struct is POD and a class is not.

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.

------
Jormundir
No defaulting to private is not backwards. It enforces having a reason to make
something public, which is a stronger default when it comes to building well
abstracted, decoupled, modular code.

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.

~~~
bad_user
Precisely, C++ code is usually not riddled with all kinds of bugs and buffer
overflows. </sarcasm>

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.

~~~
eropple
_> Precisely, C++ code is usually not riddled with all kinds of bugs and
buffer overflows. </sarcasm>_

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.

~~~
shmerl
You probably meant the stdc++, not the STL. But I agree, in C++11 one can use
smart pointers which help avoiding many memory management pitfalls and make
memory ownership mode more explicitly defined through the language itself.

~~~
wfunction
People nowadays never mean SGI (or anything other than the C++ standard
library) when they say "STL", so it's a good time to stop correcting them.

~~~
shmerl
Still, it's not exactly correct. Unless you read STL as STandard Library.

------
10098
> Members of a class in C++ are private by default, but members of a struct
> are public by default.

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).

~~~
nicolasgz
> you should always prefer private to protected and protected to public

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 OOP

That's cargo cult programming. Using "class" doesn't make your code OO. The
language we are programming in is C++, not OOP.

~~~
eropple
_> That's cargo cult programming. Using "class" doesn't make your code OO._

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.

------
xerophtye
So... the main argument is that we can use "struct" instead of "class" so
class is useless and awful, and that using "class" is brain-dead? And the
author cites that use of class is absurd because it makes the default access-
specifier "private", thus leading to more code?

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.

~~~
10098
Correction: the default access level in C# I think is that the name is visible
to all the members of the given assembly, but not outside of the assembly. I
don't remember what it's called though.

~~~
ygra
And in Java it's package-visible.

------
alexchamberlain
This is an awful article. It is extremily rare to choose `struct` vs `class`
because of their default visibility. It is much more usual because of style.

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?

------
talles
"More verbose"? Just how... you tell me. A line? This no
JavaScript/Coffescript land, this is freaking good old C++. Don't tell me
about verbosity on this level.

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.

~~~
nicolasgz
> 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.

~~~
talles
By the way C++ standardized it? Yes, the only big difference is property
accessors.

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.

------
linhat
I wish I could upvote this more than just once. Using 'struct' instead of
'class' and combining that with templated "pure functions" [1], when
applicable, make for some really readable/maintainable/extensible C++ code,
which, although often overlooked, is a _multi_ paradigm programming language
(the OOP proponents want you to believe otherwise ;-). Especially, as
mentioned in the article, the fact that if you're honest you _almost never_
really need private class members (that might later force you to create
set/get-ters) really resonates.

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...

[1]
[https://en.wikipedia.org/wiki/Pure_function](https://en.wikipedia.org/wiki/Pure_function)

[2]
[https://en.wikipedia.org/wiki/Opaque_pointer](https://en.wikipedia.org/wiki/Opaque_pointer)

------
mackal
The thing about templates is kind of silly, AFAIK, they added typename since
the use of class didn't really make sense for the reasons he did state. They
made an error in other words and corrected it in a latter release of the
standard and best practice would be to use typename unless you need
compatibility with an older compiler that doesn't support it.

------
zokier
> When forward declaring a class/struct, you must use the same keyword which
> it was declared with.

Wrong.

    
    
        struct Foo;
    
        class Foo {
        };
    
        int main(int, char**) {
                Foo f;
        }
    
    

compiles cleanly with -ansi -pedantic -Wall -Wextra besides warning about
unused variable.

~~~
Patient0
Thanks for confirming - this was the one statement that struck me as wrong too
but I don't have a C++ compiler readily to hand on my iphone

~~~
nicolasgz
Although it should be possible per standard C++, Microsoft's compilers have
trouble dealing with it.

------
vrnm
I like to put the public interface of classes before the private
implementation details. For this reason I always use struct. It saves some
typing and decent C++ programmers know the difference. You cannot enforce any
of these extra semantic meanings in code, so I consider them to be a waste of
time anyways.

------
prof_hobart
So when using a class as a struct (all public member variables and unless I
missed it, no function), it's better to use the keyword "struct" rather than
"class"? Say it ain't so...

~~~
eropple
To the best of my knowledge, you can use methods in a POD struct so long as
it's not polymorphic. With no vtable, it'll be represented as a C struct
would. It's not header-compatible with C, though.

~~~
nicolasgz
There are no rules to limit the kinds of member functions you can add to a
struct. Structs can be polymorphic, can have vtables, and don't need to be
compatible with C.

~~~
eropple
Yes, I know. As discussed elsewhere in this thread, there are cultural
connotations to the term 'struct' that lead it to be used almost universally
for POD, but--to ensure no ambiguity--that's why I said 'POD struct'.

------
abcd_f
Amen! Having programmed in C++ for close to 20 years now, I converged to using
_struct_ a while ago and yet to run into a case where it would create problems
(some conditions apply, see below).

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.

~~~
stinos
> You want to make a part of a struct private? > /* private * /

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?

~~~
huhtenberg
If someone really wants to touch a private field, there's more than one way to
do that. So "private" merely serves as a safeguard against honest mistakes. In
this capacity it is a close sibling of that "if (0 == x)" contraption. It
essentially says that I don't trust myself or others to not make dumb
mistakes, so here's a safeguard for that. Not that it's a bad thing to have,
but I can easily see that it can be deemed redundant to just having strong
coding ethics.

~~~
eropple
"Coding ethics" stop buffer overflows too, right? ;-)

~~~
huhtenberg
It's "discipline", not "ethics". I just had a brain spasm.

And, yes, it surely stops them better than some flimsy member access
restrictions.

~~~
eropple
As opposed to a private array and a public iterator API?

~~~
huhtenberg
Naughty hands will find a way to break a container/iterator metaphor just the
same as a simple buffer. Point being is that it's much better to work with
competent developers than to needing to rely an idiot-proof coding style.

------
Nzen
for tl;dr : class << struct. Struct inherits members publicly by default, is C
compatible, and isn't ambiguous in forward declaration.

------
mariusz331
i dont think he gets c++

~~~
abcd_f
I'll tell you a secret - nobody gets C++

;)

------
jokoon
it was just advertisement that targets java developers.

------
kunil
You can always

    
    
      #define private public
    

(!)

------
Theriac25
Game programmers are weird.

~~~
eropple
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.

~~~
pmr_
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.

~~~
eropple
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.

------
blahbl4hblahtoo
There have been a lot of these articles lately...it seems to be fashionable to
dislike OO and C++ OO specifically.

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...

------
goggles99
Worse than goto?

------
evincarofautumn
Yawn. C++ is terrible in myriad ways, it’s widely acknowledged; we’re just
stuck with it for a little while longer until its replacements mature a bit.
Besides, “static” is worse.

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?

~~~
p1esk
Is it better than C?

~~~
xerophtye
Nope. C rocks. C is way way more powerful. Yes, they don't really teach the
power of C in Programming 101, but take High Performance Computing. That's all
C

~~~
eropple
HPC is not "all C"; there are very, very large Java and C++ presences in both
the academic and financial HPC spaces.

~~~
ygra
And Fortran.

