Readability Advantages of C over C++
C++ is a language that was created to improve some of the features and use cases of the C language, in order to make it easier to use for application development (instead of system programming, the main area dominated by C). One of the perceived problems in C is the lack of support for object oriented features that are so common on the development of desktop applications. For example, C lacks the concept of a type that encapsulates code and data. While it is possible to program in an object oriented style in C, it is somewhat cumbersome to use such a style.
In order to make C easier to use, C++ designers added a number of features that would be more appealing to programmers. Inheritance was one of them, used to support object oriented features. Overridden methods were also added to improve object oriented programs.
C++ also added some features that can be considered syntactic sugar for already supported operations. For example, operators can be overloaded, so that many math operations, and even punctuation such as “,” can be overloaded by programmers. Normal functions can also be overloaded, by providing versions that differ on the number and type of arguments.
Later on, C++ added templates to fix a problem with the language’s type system. With templates, it is possible to instantiate a class based on one or more types. This allows for the creation of containers, such as the ones found in the STL. Vectors, maps, and multimaps can all be created by adding a type as a parameter for template instantiation.
Consequences
Although C++ designers succeeded in creating a language with support for most object oriented features, there are a lot of unintended consequences of the way many of these features were introduced.
Unlike C, in C++ it is difficult to understand, by just looking at the code being written, what will be really executed at run time. This has always been a problem with object oriented languages due to polymorphism. However, the problems have been compounded by the liberal use of overloading features in C++ programs.
Clearly, in C it is possible to write convoluted programs (especially if one wants to use the preprocessor). However, in general one just has variable declarations, function declarations, function calls, and simple expressions (such as mathematical and logical expressions). Maybe the results of a function call may not be completely understood by the programmer, but from the syntactical point of view it is easy to figure out what is going on in the program.
And, to put it clearly, the problem is not that the function or class is doing something we don’t know. The problem is mostly in trying to figure out what is happening in a given line of code. In C is very easy to figure out what is being called (up to macros): just read the manual for the functions being used and you will have a good idea of what is being executed.
In C++, on the other hand, a large number of things can be happening in a single line: an overloaded operator, a type conversion, a template instantiation, an overridden function in one of a dozen of classes, a constructor called in some part of the hierarchy, in some namespace… Who knows? You have to be smart enough to figure out what is going on in each of these cases. As your code base grows, this makes it increasingly hard to understand what is going on.
And this is not even considering issues such as exceptions, which are a huge liability, since you have to check that they will leave your program in a reasonable state at each part of your code.
Conclusion
While C++ provides a lot of helpful features for application programming, these features have a cost. It becomes increasingly difficult to understand what is going on in each line of code, unless the developers are very disciplined.
This also shows a little of the myth surrounding the idea that C++ is better than C for large code bases. While C++ has some features that might be helpful, in general the bigger the C++ code base the harder it is to understand due to these issues.
This is true even for automated tools. It is very difficult to create automatic tools to parse and change C++ (for example, to perform refactoring). In comparison, C is much easier to understand, and one can do a lot with tools such as ctags. It is not a surprise that large scale projects such as the Linux kernel use C without any problem.