top | item 11978875

My Most Important C++ Aha Moments (2006)

100 points| adamnemecek | 9 years ago |artima.com | reply

81 comments

order
[+] humanrebar|9 years ago|reply
> Visitor lets you define a new operation without changing the classes of the elements on which it operates.

Yes, but that's not the real point. You can do that in other ways. Creating a new std::algorithm does that, for example.

The real purpose is letting one function be polymorphic in multiple directions. This is called multiple dispatch. Some languages support this as a built-in feature, but C++ doesn't, so a couple different design patterns were invented to fill in this gap. The Visitor pattern is the most popular and is probably the easiest to work with.

https://en.wikipedia.org/wiki/Multiple_dispatch

That is, it lets you do this:

    polymorphicOnThis->doSomething(alsoPolymorphicOnThis);
That is, for each permutation of the two types (polymorphicOnThis and alsoPolymorphicOnThis), you can define new specific behavior.
[+] munificent|9 years ago|reply
You can use visitor to implement multiple dispatch, but that's not it's "real" point. The real point, as stated, is to allow polymorphic methods that aren't defined directly on the class.

I've seen a lot of implementations of the visitor pattern, and almost all of them used it for single dispatch.

[+] humanrebar|9 years ago|reply
> Realizing that C++’s “special” member functions may be declared private

Don't do this anymore! Just delete them:

    MyClass& operator=(const MyClass&) = delete;
Private-really-means-deleted was a cool and very useful trick before C++11. So useful, that it was a shame to require secret knowledge and aha moments to use. So they just made it a normal feature of the language. There's also a way to explicitly use the default implementation:

    MyClass& operator=(const MyClass&) = default;
[+] hendzen|9 years ago|reply
There is an obscure pitfall of making a class noncopyable by making the copy constructor private.

Consider the following class:

  class X { 
   private:
     X& (const X&); // not defined
   public:
     X bar() {
        X x = ......;
        return x;
     }
   };
Due to programmer error, an instance of X is returned by value despite the class being noncopyable. The copy constructor being private doesn't help as bar() is a method of X. This will compile and link, despite the copy constructor being undefined. I will leave the reason for this as an exercise for the reader.
[+] kmiroslav|9 years ago|reply
Interesting, I didn't know about `delete`.

Come to think of it, the trick to make something private in order to "remove" it is one of these very few areas where C++ makes you pay for something you don't use, so I'm not surprised that there is now a special keyword (well, a repurposed keyword) to address that.

[+] MaulingMonkey|9 years ago|reply
> Private-really-means-deleted was a cool and very useful trick before C++11

Rather, until every compiler you need to target supported this specific C++11 feature. In other words, it's still a cool and very useful trick ;)

[+] kazinator|9 years ago|reply
> that it was a shame to require secret knowledge and aha moments to use

But Myers had this aha moment about private constructors in 1988! Since then, this has been covered in countless books, tutorials and coding convention documents.

A newbie still has to read something in order to learn about "= delete". This is not "discoverable" just by experimenting with the language!

Knowing that delete is a keyword, and that there are declarations of the form "specifiers fun-declarator = blurb" you are very unlikely to discover, on your own, that the blurb may be the keyword "delete", and that this actually compiles and has a certain useful effect.

However, the combination of constructors and "private:" is discoverable, as Myers' 1988 aha moment shows. It's a logical combination of independent features.

It's okay for techniques in languages to be discoverable logical combinations of features rather than arbitrary syntax thrown in.

It's also okay for the culture which surrounds a language to have a body of techniques which are carried in that culture, rather than shoehorned into the language parser.

[+] kazinator|9 years ago|reply
Alternative view: if you must use C++, stick to nothing later than C++2003.

Anyway, declaring a constructor " = delete" isn't the same thing as making it private. If it's private, the code in your class scope can still use it. If you can't trust your class private code to do things correctly, then you're screwed; go join IT and write backup shell scripts. So basically this "= delete" is just another ear growing out of the elbow of C++.

[+] stupang|9 years ago|reply
I love C and Objective-C. I can't stand C++.

Is that common among programmers?

[+] hellofunk|9 years ago|reply
It's easy to dislike or hate C++ due to its immense complexity, and programmers like to be able to keep simple abstractions in their head so they can concentrate their energies on their problem domain without worrying about language confusion. With C and many other languages, this is possible as they are smaller languages. C++ on the other hand: is there any language with widespread use that is so deep and complex? However, there are undeniable conveniences to C++ (safety, a good library, much more -- especially functional-style programming with lambdas now) that can speed up your work process, and if you can accept that you will never know the entire language and can just use those bits that make things easier, it is possible to have a healthy relationship with the language. And it offers tremendous room to grow as you get more and more comfortable with it. Few languages allow you to just keep diving in deeper and deeper as you desire, while still letting you get to work right away without being a master. Even template metaprogramming alone is gigantic area of ongoing research -- the stuff you can do with it is mind-bending and unavailable in nearly all other languages. Templates are, after all, one of very very few wholly functional, immutable languages out there. And template instantiation is the underlying force behind many of the modern features like lambdas that allow you to access that power without actually knowing templates well. It's a powerful language for which you must accept its character flaws in return for its abilities.

It's doesn't hurt either that the libraries available in C++ are really cool.

[+] pjmlp|9 years ago|reply
I love C++ except the copy-paste parts from C and the toolchain compromises used to sell it to C developers.

Dislike Objective-C verbosity and C roots, although I kind of like its Smalltalk influence.

Really strongly dislike C and the culture of insecure software it has brought into our industry.

[+] _pmf_|9 years ago|reply
C programmer here; I don't like C++ much because every library tends to reinvent the whole stack (or maybe that's just my impression from using MFC and Qt, which are notorious in that regard).

RAII and scope based construction/destruction is actually quite nice.

[+] Tomis02|9 years ago|reply
The more I learn C++, the more I can't stand it. Its ever-increasing complexity keeps being a distraction from the actual problem you're trying to solve.
[+] blt|9 years ago|reply
Among many reasons, I would choose C++ over those languages because it has operator overloading. Expressing 3D spatial math and linear algebra in a language without operator overloading is incredibly tedious.
[+] johnydepp|9 years ago|reply
Coming from C++ and iOS world I would say recent C++ has evolved a lot. And I think its better than Objective-C.
[+] mratzloff|9 years ago|reply
Have you tried modern C++ (that is, C++11 and C++14)? It has a very different feel these days. I used to prefer C as well, but C++ has come a long way in ease of usability.
[+] gurkendoktor|9 years ago|reply
It all depends on what you are building. Objective C is absolutely fantastic for rapidly developing GUIs because of its dynamic runtime and flexible typing. On the other hand, C++ makes it a lot easier to write efficient, (relatively) safe data structures.

I find it extremely frustrating when I have to use either language in an area that it wasn't designed for.

[+] hacker42|9 years ago|reply
What has always bugged me about C++, but maybe I am overlooking some reason why this generally cannot work, is that it does not resolve circular dependencies such as this one:

    // file: A.h
    class A {
      B* _b;
    };
    
    // file: B.h
    class B {
      A* _a;
    };
I mean a pointer has a fixed size, so couldn't the compiler just leave some sort of type placeholder in class A until class B is eventually defined.
[+] saynsedit|9 years ago|reply
Yep the beauty (and maybe curse) of C++ iterators is that they are a faithful abstraction of pointers.
[+] aksx|9 years ago|reply
some people would argue that pointers themselves are a type of iterator
[+] hota_mazi|9 years ago|reply
My most important C++ Aha moment was in 1995 when I wrote my first lines of Java and realized that it was possible to write OO code without having to fight the compiler every step of the way.
[+] digler999|9 years ago|reply
My Aha moment was in 2008 when I saw a java program consume 400+mb of RAM for a text editor. Then if you clicked on too many things, it crashed under its own weight (eclipse).

"But it has garbage collection" they said. "You dont have to worry about pesky memory managment, the language has an intelligent VM that handles it for you!".

[+] zxcdw|9 years ago|reply
Does this reflect your view regarding development in C++ and Java and is your comment merely a lazy reflection of that?