Why C++ is not my favourite programming language

The body of a destructor is executed before the destructors for member objects. Destructors for nonstatic member objects are executed before the destructors for base classes. Destructors for nonvirtual base classes are executed before destructors for virtual base classes. Destructors for nonvirtual base classes are executed in reverse order of their declaration in the derived class. Destructors for virtual base classes are executed in the reverse order of their appearance in a depth-first left-to-right traversal of the directed acyclic graph of base classes; “left-to-right” is the order of appearance of the base class names in the declaration of the derived class.

11 responses to “Why C++ is not my favourite programming language”

Oh, well, destructors aside, is funny to see how constructors of static classes (if poorly written) may add spice to debugging an application).

C++ is not the worst language of the world. Thou I still prefer C, C++ can be quite fun, as long as you don’t mess with STL and you don’t use many templates. (they can be usefull, just don’t abuse ’em). The real enemy is OOP, a too academic style for modern programming.

In order to achieve full OOP design you should use too much time for analysis and design (and nowadays nobody is willing to pay for that wasted time). The result of not doing a good planning is the C++ tentacled monsters we’re fighting every day.

C++ can truly be a nightmarish language only if is handled by non-competent programmers, just as BASIC was.

“If you think C++ is not overly complicated, just what is
a protected abstract virtual base pure virtual private destructor,
and when was the last time you needed one?”
— Tom Cargill, C++ Journal, Fall 1990

I agree to a point, but you must realize that all languages do some things for you, and it is better that these be a) defined, and b) made known, if they could have potentially observable consequences. One thing that makes this quote look difficult is that Stroustrup is writing in a formal manner in order to be precise and unambiguous, things I wish all programmers could be. The more substantive source of complexity is the ‘feature-richness’ of C++; in this case, virtual inheritance, multiple inheritance and multiple storage classes add to the complexity of destroying an object.

If you think this is complex, check out how the Java memory model has posed some subtle problems in understanding the behavior of multithreaded programs, especially on multiprocessor computers. C++ is no better, but my point is that complexity is not exclusive to C++.

It is the interaction of C++’s many features, I believe, that is the source of the language’s complexity. In his writing, Stroustrup is always able to make it look reasonable, and I recently realized how he does this: C++ has multiple goals, which are, to some extent, at odds with each other, so he is always able to pick a subset of them to justify any feature of the language or aspect of its use as being not necessarily ideal, but the best choice in the circumstances.

That section you highlight isn’t really necessary knowledge for day-to-day programming. In twelve years of C++ programming, I can’t remember a single time where I had to care about the order of destruction within an object.

It is important to have the destructor order defined, but in general C++ is defined to do “the right thing” and a programmer can just go back to working on something else. Now if you write C++ compilers, you have my deepest sympathies.

A bigger gotcha tends to be people calling virtual functions within base class destructors or constructors and expecting a derived member function to be called.

I just realized that the gotcha I referred to *is* because of dtor/ctor order. Ah well… But that does seem to be the only problem I’ve ever repeatedly (but still rarely) encountered with regards to ctor/dtor order, and that problem has never been a show stopper.

Oh. And don’t get me wrong. There is plenty of things I hate about C++, but dtor order isn’t one of them.

There are some things I don’t like about C++, but this isn’t one of them. There has to be an order between class, members and base classes. The virtual classes are simply done last.

For me, I wish C++ had closures or even function pointers that could also hold an object pointer so that you could have callbacks to methods. Properties are something that Stroustrup has said he will never support. That is just braindead.

Heck, you could have talked about the syntax, by ref or by val, error messages from templates, etc. Anything but destructor order. If each destructor cleans up its own storage, you don’t even have to know the order.

Vorlath: just so. Order of destruction is one of the things that C++ did right. There are so very many things it did wrong. Things that spring immediately to mind:

– the crazed context-sensitive grammar, which got so complex that ridiculous syntaxes had to be defined to avoid introducing Yet One More Keyword: the =0 madness for pure virtual members and the syntaxes for partial template specialization and nested templates, for one. (The new C standard finally allows you to not add a space between double closing template angle brackets). More generally, template syntax is atrocious: templates themselves make much more sense in ML than in C++, but retain a lot of their fundamental elegance even so. It’s a shame that it took so long for useful tricks using them to come to light (and nearly all of them are due to one man, Alexei Alexandrescu).

– while we’re on the syntax boat, the ridiculous syntax for declaring implicit conversions (‘operator char *()’, anyone?’) and functors (operator()(), yes, it’s nice to have stateful nested functions in a C-like language at last, but the declaration syntax is insane).

– the existence of user-defined implicit conversions at all, and the demented hacks the language had to define to avoid this causing problems (chains of implicit conversions were forbidden).

– the STL’s design is gorgeous, but the language really should have had a mechanism for making the error messages comprehensible. (Concepts, the mechanism eventually decided upon after standardization, was considered for the new standard and then dropped.)

– the ‘export’ keyword and separate compilation of templates. Never ever ever standardize anything you haven’t implemented! ‘export’ doesn’t open a can of worms: it opens an uncloseable gateway to a galaxy entirely populated by clones of Great Cthulhu, has horrific impacts virtually everywhere, and has nearly none of the benefits you might think it has on first sight. (I am still astounded that anyone, even the EDG geniuses, actually managed to make it work.)

– While we’re on the subject of implementation difficulty, C++ is a horror. Forget the parser. This is a language which sneaks the ability to run arbitrary code at compile time in through the back door (via templates and, get this, sizeof()), so the poor damn compiler implementor doesn’t structure the compiler to make it easy to do this sort of thing from the start (as a Lisp compiler hacker would), but notices it only later and is now in for a world of pain retrofitting their existing code to work properly. What’s worse is that unlike Lisp the language in which the arbitrary code gets run at compile-time is not the same as the runtime language, but is rather the type system!

I could go on for hours. I used C++ for years, but these days I’d prefer to use almost anything else. Except PHP.