It's annoying, it's a drag on productivity, but in the long run it's arguably necessary.
Some other languages which reduce verbosity by making more things implicit make it harder to understand what's actually going on behind the scenes. You lose a lot of information.
Also in the "hiding stuff behind the scenes" department C++ is quite bad.
SomeClass someMethod(SomeClass a, SomeClass b) {
...
}
is doing a lot behind the scenes. Code below is better but it's longer and less convenient to write. const SomeClass& someMethod(const SomeClass& a, const SomeClass& b) {
...
}
And actually C++ code isn't easy to reason about wihtout reading the whole program. It isn't even easy to parse.What's going to happen when you run this?
y = f(x);
It may be that f is function, or a type. f may return the correct type to assign to y, or it may return something else and automatically run some conversion. There may be copy constructor and some destructors involved if it's returning object and not reference. It may run overloaded operator= and do anything at all, for example add f(x) to y. Hell, f can also be a class with operator() overloaded, and you would need to track its state to see what will happen.And we haven't even touched the subject of #define.
It's much easier to reason about Java code for example.
Zero-overhead abstraction is a key talking point of the language. Virtual-by-default would contradict this entirely.
These days, the economy of a vtable pointer is not really a good reason, and all languages that have the opposite default (such as Java, as you point out) are doing quite fine.
Because of this default, I can't count the number of times where I've seen "#define private public" and other horrors that developers used to be able to extend classes that their creators were too short sighted to design properly.
If anything, the performance difference between std::vector<shared_ptr<Foo>> and std::vector<Foo> is even greater today than it was twenty years ago.
Not being able to inline a method like (from vector)
T& operator[](size_t pos)
{ return data[pos]; }
Would kill performance.In languages which do run-time optimisation you can inline such methods later, but in C++ that's not possible and proving when you can de-virtualise a method (which most compilers do) is very hard and often fails.
The reason the previous commenter asked if you're from the java world is because in many highly important areas, the effect on memory and speed this would cause would be unacceptable. These areas _tend_ to be left to people who understand languages like c, though, so a lot of newer languages make decisions ignoring these good use cases.
Also I don't think it's that big of an achievement to understand C. Despite its flaws it's very simple language, very different from C++.
To the point - you could ensure that compiler can de-virtualize your usage of structure (or class if you will) by adding "nonvirtual" to every method it implements or derives. I don't see how it's any better than having to delete "virtual" from every method it implements or derives. Just a question of defaults, and I'd say most of modern C++ code isn't written with the performance goals that justify nonvirtual as default. You can and should profile after writing something anyway if you care about performance.
And anyway if you have derived classes it's almost always the case that you want at least some of your methods virtual, otherways what's the point?
I am using C++ right now for embedded code but otherwise I write mostly Javascript. There was a time when C++ was the standard choice of language for desktop apps etc., but that's hardly the case any more. You choose C++ if you need performance and control. And I think the "default means the least overhead" concept makes a lot of sense there.
Also, inheritance is a very central part of mostly all Java code whereas it's much less idiomatic (modern) C++. In C++, classes serve to give you RAII and you specialize with templates.
Think it in this way. Many respectable people has been making a case to avoid inheritance[1][2]. What you are proposing would actually be an incentive to them. I don't know about you but the amount of functions that I actually override in my code is not even close to the 20%.
Why should we set a default for that 20%?
[1] http://channel9.msdn.com/Events/GoingNative/2013/Inheritance... [2] http://www.gotw.ca/publications/mill07.htm
And you do want to refactor your virtual methods and then extracted methods do usually need to be virtual, even if at first they don't they may need to become virtual in future, and IMHO it's better to just make them virtual from the start, if you don't REALLY need the performance.
You can mess up because of nonvirtual-by-default too, especially in C++ because of the difference between stack and heap objects.
struct A {
virtual int f(int x, int y) { return g(x,y); }
int g(int x, int y) { return x+y; }
};
struct B : public A {
int f(int x, int y) { return g(x,y)+1; }
int g(int x, int y) { return x+y-1; }
};
B* b1 = new B();
A* b2 = b;
B b3;
b1->f(2,2); // 4
b2->f(2,2); // 5
b3.f(2,2); // 4
This bite me a few times in C++.The override keyword was added in C++11 to help prevent the sort of mistake you were trying to show. Any methods you mark with it will result in a compile error if they are not actually overriding anything.
For example, if B::g were marked as override, it would fail to compile because A::g is not virtual.
Unfortunately, class inheritance is the only way to create the equivalent of an interface or (Scala-type) trait in C++. So, even if you avoid class inheritance in general (which is a good thing IMO), you still end up doing inheritance if you want run-time polymorphism in the form of abstract classes or abstract base classes.
In practice, most classes are designed without inheritance in mind and yet, being able to extend and override them has proven infinitely more valuable than the occasional case where such an overriding breaks the parent class.
The practical reality is that even if a class is not designed for inheritance, inheriting from it is unlikely to break it but very likely to make its user's life much, much easier.
tl;dr: Just because it's "infinitely more valuable" in Java doesn't mean the same for C++.
The first form of 'someMethod' will also accept all 4 combinations of moves and copy operations on 'SomeClass': (copy a, copy b), (copy a, move b), (move a, copy b), (move a, move b). Your second, less convenient, function results in moves degrading to copies, leaving performance on the table if 'someMethod' performs mutation.
Your 'y = f(x)' ambiguity isn't a problem in practice, since most code styles use different naming conventions for classes/structs and function names.
Conversions, construction, copy, move, and assignment semantics etc, are one of the most important, and one of the most difficult things to get right, when it comes to class design. If you make sane choices though, and put thought in to it, automatic conversions etc shouldn't be bothersome.
Whoa, no it doesn't. C++ is far more verbose than necessary for things like creating algebraic datatypes or really creating any types.
std::vector<int>::iterator it;
for (it=arr.begin(); it!=arr.end(); it++) {
...
}
as an improvement over for (int i=0; i<len; i++) {
...
}
Not entirely unrelated: I'm currently busy verbosifying a large chunk of C++11 code into C++90 code because Reasons (or so the maintainers assure me). std::vector<int> myVec;
for( auto it = myVec.begin(); it != myVec.end(); ++it );
or if you prefer the external begin/end syntax: for( auto it = std::begin(myVec); it != std::end(myVec); ++it );
or the most succinct (replace && by & if writing): for( auto && item : myVec );That is strictly not necessary. `auto&&` is what is now being called a universal reference: `item` resolves to `const int&` if `myVec` is const, and to `int&` if `myVec` is mutable. `auto&&` does the right thing in the majority of cases. In fact, the following extension [1] has been proposed for C++17 (and already implemented in recent clang builds):
for( item : myVec ) { /* do stuff */ }
which is meant to be a short-hand for for( auto&& item : myVec ) { /* do stuff */ }
[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n399... for(auto& item : vec)
syntax was merely a talking point being tossed around C++0x meetings. And to this day the project I'm working on still hasn't officially dropped support for C++90 so I'm stuck with the old syntax anyway :/ template <class T>
void foo(T arr)
{
for (auto it = arr.begin(); it != arr.end(); ++it)
{
std::cout << *it << std::endl;
}
}
You could pass a `std::map<int>` to `foo`, or a `std::list<string>`, or a `std::vector<char>`. You could even create your own classes and give them to `foo`, as long as they implement the `begin`/`end` protocol.It's certainly more verbose than necessary, but it can be convenient.
Ideally, it should be something like:
for (auto it : arr) {
// do something with *it
}The advantage of iterators is that they're incredibly flexible. You can use them for sub-ranges, reversed ranges, non-ranges like input and output iterators, etc, etc. This is vastly more powerful than something like, say, Objective C's NSFastEnumeration, which just allows for the trivial case handled by the range-based for-loop.
Because there are algorithms where you may not want to walk through the whole collection. STL wasn't meant to be a container library alone, it also includes many generic algorithms that work using iterators to delimit the range of data to be operated upon.
Times have changed now of course.
Just to write a class in C++ with a constructor and destructor which are not inlined, you have to repeat the class name about seven times: three times in the class declaration. Then four more times in the definitions of those two functions:
class verbose {
public:
verbose();
~verbose();
};
verbose::verbose()
{
}
verbose::~verbose()
{
}I don't have a link - it was in some recent conference. He stated that every time he added a new feature everyone would be up in arms and demand a really verbose implementation, which he added reluctantly. Now that everyone is used to the features they complain about how ridiculously verbose it all is.
There isn't any reason for the craziness of
template<typename T>
void foo(T a)
vs void foo(auto a)
Certainly things can become too implicit, but C++'s heritage of verboseness is due to the conservatism of the standards committee, not because anything less would be confusing. template<typename T>
void foo(T a, T b)
vs void foo(auto a, auto b) template<typename T, typename U>
void foo(T a, U b)
:)C++'s type system is actually pretty strong, but the amount of boilerplate that is needed to create a new type means that it is very difficult to program in a type safe way... without being incredibly verbose. Creating a type safe "Length" type is too much of a pain in the ass for anyone to actually do it.
Which is what I mean by "too verbose". It is so verbose that instead of securing the "specific and obvious" in strong compiler guarantees, we fake it with implicit conversions and typedefs.