C++: the Ugly Useful Programming Language

“Aren’t you going to pack this, Mother?” Roberta asked, pointing to the beautiful cabinet inlaid with red turtleshell and brass.

“We can’t take everything,” said Mother.

“But we seem to be taking all the ugly things,” said Roberta.

“We’re taking the useful ones,” said Mother; “we’ve got to play at being Poor for a bit, my chickabiddy.”

When all the ugly useful things had been packed up and taken away in a van by men in green-baize aprons, the two girls and Mother and Aunt Emma slept in the two spare rooms where the furniture was all pretty.

— from The Railway Children by E. Nesbit

Eric Raymond, editor of the [Computer] Jargon File and author of The Cathedral and The Bazaar and a number of well-used but little-known pieces of software, is working on a book, putatively titled Why C++ Is Not Our Favorite Programming Language. In his recent announcement, he lays out why he wants to “harpoon the Great White Whale of programming languages”:

C++ is an overcomplexity generator. It was designed to solve what turned out to be the wrong problems; as a result, it lives in an unhappy valley between two utility peaks in language-design space, with neither the austere elegance of C nor the expressiveness and capability of modern interpreted languages. The layers, patches, and added features designed to lift it out of that valley have failed to do so, resulting in a language that is bloated, obfuscated, unwieldy, rigid, and brittle. Programs written in C++ tend to inherit all these qualities.

In the remainder of this paper we will develop this charge into a detailed critique of C++ and the style it encourages. While we do not intend to insult the designers of C++, we will not make excuses for them either. They repeatedly made design choices that were well-intentioned, understandable in context, and wrong. We think it is long past time for the rest of us to stop suffering for those mistakes.

C++ is my own favourite programming language, not that I am any great expert, given that the only other language in which I have brought any other project to fruition is Java, and that was in 2004. This is not to say that C++ does not have its fair share of annoyances, but as the title is not Why C++ Sucks but simply why it’s not their favourite, I will lay out why it remains mine, and more to the point, why it endures despite the existence of alternatives such as Java.

To be fair, I don’t know if Raymond and his friend Rob Landley have the same bugbears about C++ as the people who have put out various “reformed” object-oriented C-derived programming languages, but the results usually involve the stripping out of not only the irritating features and bloat, which may be a consequence of layering object-oriented features onto an existing language, but a whole lot of useful features as well. The usual suspects are operator overloading, multiple inheritance and the macro preprocessor. Java got rid of all three, C# and D, a more recent attempt, get rid of all but the first. (Note: I will attempt to explain the terminology in layman’s terms.)

Operator overloading is programming an operator (i.e. a mathematical symbol or brackets) to do what you want them to. This means that, when you’re writing code to handle lists or other data structures, you can use symbols, or allow the programmers who use your code to use them, to manipulate or chop up their data by using the plus sign to add a bit onto the end of the string or list, to use an equals sign to test for whether two strings are identical, and to use square brackets (as was common in C) to identify a particular item in the list. You cannot do any of this in Java, so to identify item three in a list, you have to type something like “list.item( 3 )”, rather than simply “list[3]”.

The reason commonly given for stripping out this feature is that it facilitates obfuscated code (i.e. code whose meaning cannot be easily discerned when another person takes over its maintenance or wants to use it to build something for himself). However, they are also commonly given perfectly sane and logical meanings, such as + for adding and = for testing sameness.

Multiple inheritance is described here; it means that your class (a sophisticated type of data structure, which includes functions as well as data) can include the features of two or more classes, rather than just one. A common criticism of it is that nobody ever uses it; Jesse Liberty, in his book on C#, had said that in years of teaching C++, he never used it other than to demonstrate to students that it could be done, and he’s never missed it as a C# programmer. The toolkit I use to write the blogging client I used to write this article offers multiple inheritance as one way of implementing forms designed in their form designing program, Qt Designer, and I use it myself (not all the time, but some of the time). So there goes the claim that multiple inheritance has no uses or that nobody uses it.

Finally, the macro preprocessor. This is a means of getting the compiler to substitute one piece of text for another when the program is built. What use could that possibly be? For one thing, you might just want to have to save a regular long bit of typing, but macros have other uses. Suppose you don’t know which version of a particular library your end user will be using, and perhaps a given class will be present in a later version but not an earlier one; you might want to allow the newer class to be used if it’s there, and the older one if it’s not, and use the same word to refer to them both because they have similar interfaces, and perhaps the library tells you (via a macro) which version is present, which enables you to exclude bits from your program which only pertain to the newer library. I use this feature myself in QTM; newer versions have a lightweight plain-text editor while older ones don’t. I can do this in C++ because of its preprocessor, and more to the point, I can exclude bits that are not needed from the finished product, which makes things a bit more efficient.

The preprocessor even allows for features to be added to C++, such as the “signals and slots” feature in Qt (signals and slots means pre-arranging for one thing to be done when another thing happens, such as a web page to be loaded when you type in an address and press Enter). Most of the methods I have seen for implementing this feature in C++ use macros, and although there are alternatives, the macro-based system used in Qt is the cleanest and least complicated I have come across.

The Jargon File has an entry for what he calls a “bondage and discipline languages”, which is a language “that, though ostensibly general-purpose, is designed so as to enforce an author’s theory of ‘right programming’ even though said theory is demonstrably inadequate for systems hacking or even vanilla general-purpose programming”. A typical example is Pascal, about which Brian Kernighan, co-originator of the Unix operating system and documentor of C, wrote an essay entitled Why Pascal is Not My Favorite Programming Language, the reasons essentially being that it is a teaching language unsuited for serious programming, lacking an awful lot of functionality that C programmers (C++ had not yet been invented then) take for granted. Kernighan noted that Pascal had been extended in various ways, but that these extensions resulted in various incompatible versions of Pascal; one criticism of C++ is that, because of its complexity, different programmers learned different subsets of it, such that these programmers have difficulty working together on a project in the same language.

C++ is the opposite of Pascal; it gives you everything that C does (and Pascal doesn’t), and layers object oriented features on top of it, basing them on C’s existing data structure syntax (rather than a bolted-on one, as in Objective-C). Perhaps some might say “C++ has the exact opposite problems to Pascal”, but others might say it gives you freedom, treats you like a proper programmer rather than like a student, and allows you to program “straight to the metal”. Many of the “C++ replacements” are not designed for the last purpose; they are designed for programming virtual machines, i.e. other computer programs, rather than actual computers, and often for less serious applications, such as in-house database front-ends. There are very few proper applications, especially commercial applications, written in Java or C#, simply because they are not as fast as any program which actually runs on your computer.

Java and C# are a step away from the freedom of C and C++ towards a dictated programming style; they hide features of C++, such as pointers, to make it less easy to make mistakes, when the ability to use or not use pointers is power and flexibility, even if there are more pitfalls. Java makes it easy to “finalise” a class, meaning anyone who wants to use the class in their own programs cannot build their own classes on top of it. This is possible in C++ as well, but it does not seem to be as common. Java’s string class is final, for example, as is the window class in the Standard Widget Toolkit (SWT) used in Eclipse. Of course, some might say it’s not good programming practice to put all your application’s functionality into the window class, but it’s a programmer’s choice. If I pay money for a class library, I do not wish to be dictated to how to use it; if it’s free, it is hardly logical that you can freely redistribute or modify a class, but you cannot subclass it! (Perhaps this is compensated by the fact that in C++, any function in a class can be declared virtual, meaning that it can be overridden by having a function of the same name in a subclass, but the default is that it is not; by contrast, all functions in Java classes are virtual.)

Then there is the added verbosity of Java: the fact that you cannot put all your public, protected or private functions or data in a list, with “private:” or whatever at the top, as you can in a C++ class header, for example. You have to put public or private next to each item. Your “main” function has to be “public static void Main”, when in fact Main is always “public static void”, so why can you not just put “Main”? Why does Main have to be void anyway, preventing you returning an exit value (to tell whichever program called yours how it finished, i.e. whether the job got done or not)? Why does Main have to be in a class at all?

Bjarne Stroustrup, the inventor of C++, is quoted as saying that “within C++, there is a much smaller and cleaner language struggling to get out”, and Raymond adds that many hackers would say that this language was Java. However, Java is a stripped-down language intended for programming a closed system in a specific style, while C++ gives you the computer, allowing you to manipulate objects as flexibly as C allows with raw data. Perhaps somebody can come up with a new language which does all these things as well as C++ does now, with all the power that C++ has and Java takes away, and none of the annoying features. Otherwise, we will end up with yet another stripped-down C-like object-oriented language, probably with yet another standard library with a different vocabulary, and which is incompatible with all the others - a problem which C++, despite its groups of programmers who learn different subsets of C++, does not have: they can all at least use what others develop.

I find some of the complaints about C++ to be petty. One complaint was that, on encountering the “< <” symbol used in a “Hello world” program in a popular C++ tutorial, he “got lost”. This is the fault of that one book (my tutors at Kingston University did not explain it all that well, either), not the language; it is a function disguised by a symbol. He also mentions that he asked “what’s with the colons?”, presumably meaning the “::” operator, known as the scope resolution operator. This actually makes it clear whether what is to the right of it pertains to the class itself (like a public static method), or to an object of a class; why would anyone want to get rid of an operator which makes this explicit?

A few years ago, in response to a question I posed at a Linux Expo in London, I was told that C++ sucked, and was for programmers who could not implement object-orientation in C, as the GTK+ graphical toolkit supposedly does. Matthias Warkus, in The Official Gnome 2 Developers’ Guide, notes that “to put it bluntly, defining a class in GObject [the basis for GTK’s so-called object orientation] isn’t easy” and that the procedure would “look quite awkward” to anyone used to C++ or any other object-oriented language. The FAQ for GTKmm, the C++ interface to GTK, claims that “the derivation of new widgets in GTK+ C code is so complicated and error prone that almost no C coders do it”. However, C++ offers a ready interface to a C-based graphical library. It, and not Java or C#, let alone Python, is the logical choice for developing non-trivial, object-oriented graphical applications.

Yet another complaint, from this article (not by Eric Raymond, who says that the author “understands that C++ sucks, but he’s enumerating symptoms rather than dissecting causes”) also entitled Why C++ Is Not My Favorite Programming Language, gives the example of a Perl script which manages to grab content off the web and output it in five lines, while the equivalent in the C++ library he chooses to use as an example takes twenty. Qt can do the same in considerably fewer lines (note that SomeClass can be any subclass of QObject, which provides Qt’s signals and slots, http is an object of class QHttp and textBrowserObject is an object of class QTextBrowser, both of which are QObject subclasses):

SomeClass::someFunction()
{
http = new QHttp( "www.demiurgestudios.com" );
connect( http, SIGNAL( done( bool ) ),
this, SLOT( handleDone( bool ) ) );
http->get( "/blog/2007/10/why-c-is-not-my-"
"favorite-programming.html" );
}

SomeClass::handleDone( bool error )
{
if( !error ) {
textBrowserObject->setHtml( QString( http->readAll() ) );
}
}

That’s twelve lines (excluding whitespace and with the connect and get calls each reduced to one; they have been split to fit them on the page), and five of actual tests or calls to functions. Why does the result of the GET request have to be in another method? Because Qt’s HTTP requests are asynchronous, meaning that they do not block a graphical user interface’s operations (i.e. make it look like it’s crashed), so your program can keep working while the page is loading. However, even though this shows that it’s possible to write a C++ library to get an HTML document from a website and display it in less than 20 lines, the fact is that Perl does this in five lines because it’s a scripting language, and is thus necessarily a high-level language which takes care of the low-level business for you, while C++ is a low-level programming language, or rather a potentially multi-level one. Someone, somewhere, wrote the code (in C) that’s behind those five lines of Perl, and there is probably more than twenty lines of it, just as someone wrote what’s behind the five lines of C++ by which you can do it in Qt. The reason the author of that essay was frustrated is that nobody did, in the case of the library in his example.

To conclude, if C++ is to be overhauled, it needs to be in favour of something as powerful as it is, and not yet another stripped-down object-oriented language like Java. It needs to provide ready access to the C library and all the things the “safe” C++ derivatives lack. It needs to treat me like an adult, giving me the world inside my computer, not a walled garden. Can Raymond and Landley come up with an alternative that fits this bill? Then again, perhaps I am reading too much into all this, because in my experience, Qt demonstrates that producing a library which offers a sane C++ programming environment is possible. If I were to go inside the former Trolltech offices (now the Qt Software unit of Nokia) and repeat the claim, which originates here but cited in a comment on Eric Raymond’s blog entry, that there “is no reason to use C++ for new projects”, I would be presumed drunk and escorted out of the building. I would like to know what the developers of Qt would change, if anything, about C++.

Possibly Related Posts:


Share