> 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.
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.
> 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:
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.
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.
> 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.
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++.
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.
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.
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.
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.
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.
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.
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.
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.
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!".
[+] [-] humanrebar|9 years ago|reply
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:
That is, for each permutation of the two types (polymorphicOnThis and alsoPolymorphicOnThis), you can define new specific behavior.[+] [-] Tyr42|9 years ago|reply
http://eli.thegreenplace.net/2016/a-polyglots-guide-to-multi...
[+] [-] munificent|9 years ago|reply
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
Don't do this anymore! Just delete them:
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:[+] [-] hendzen|9 years ago|reply
Consider the following class:
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
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
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
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
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
Is that common among programmers?
[+] [-] hellofunk|9 years ago|reply
It's doesn't hurt either that the libraries available in C++ are really cool.
[+] [-] pjmlp|9 years ago|reply
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
RAII and scope based construction/destruction is actually quite nice.
[+] [-] Tomis02|9 years ago|reply
[+] [-] blt|9 years ago|reply
[+] [-] johnydepp|9 years ago|reply
[+] [-] mratzloff|9 years ago|reply
[+] [-] gurkendoktor|9 years ago|reply
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
[+] [-] saynsedit|9 years ago|reply
[+] [-] aksx|9 years ago|reply
[+] [-] hota_mazi|9 years ago|reply
[+] [-] digler999|9 years ago|reply
"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
[+] [-] kazinator|9 years ago|reply
http://scottmeyers.blogspot.ca/2015/12/good-to-go.html