C++ relative to C
The lineages of C and C++ both trace their lineage back to the ALGOL programming language, which saw its first version in 1958 (ALGOL 58), followed by updates in 1960 and 1968. ALGOL introduced the concept of imperative programming—a programming style in which statements explicitly tell the machine how to make changes to data for output and control flow.
A paradigm that emerges rather naturally from imperative programming is the use of procedures. We will start with an example, to introduce the terminology. Procedures are synonymous to sub-routines and functions. They identify the groups of statements and make them self-contained, which has the effects of confining the reach of these statements to the limited scope of the section they are contained within, creating hierarchy and consequentially introducing these procedures as new, more abstract statements. Heavy use of this procedural programming style finds its place in so-called structured programming, alongside loop and branching control structures.
Over time, structured and modular programming styles were introduced as techniques to improve the development, quality and maintainability of application code. The C language is an imperative, structured programming language due to its use of statements, control structures and functions.
Take, for example, the standard Hello World example in C:
#include <stdio.h> int main(void) { printf("hello, world"); return 0; }
The entry point of any C (and C++) application is the main() function (procedure). In the first statement line of this function, we call another procedure (printf()), which contains its own statements and possibly calls other blocks of statements in the form of additional functions.
This way we have already made use of procedural programming by implementing a main() logical block (the main() function), which is called as needed. While the main() function will just be called once, the procedural style is found again in the printf() statement, which calls the statements elsewhere in the application without having to copy them explicitly. Applying procedural programming makes it much easier to maintain the resulting code, and create libraries of code that we can use across a number of applications, while maintaining only a single code base.
In 1979, Bjarne Stroustrup started work on C with Classes, for which he took the existing programming paradigms of C and added elements from other languages, in particular Simula (object-oriented programming: both imperative and structured) and ML (generic programming, in the form of templates). It would also offer the speed of the Basic Combined Programming Language (BCPL), without restricting the developer to its restrictive low-level focus.
The resulting multi-paradigm language was renamed to C++ in 1983, while adding additional features not found in C, including operator and function overloading, virtual functions, references, and starting the development of a standalone compiler for this C++ language.
The essential goal of C++ has remained to provide practical solutions to real-world issues. Additionally, it has always been the intention for C++ to be a better C, hence the name. Stroustrup himself defines a number of rules (as noted in Evolving C++ 1991-2006) that drive the development of C++ to this day, including the following:
- C++'s evolution must be driven by real problems
- Every feature must have a reasonably obvious implementation
- C++ is a language, not a complete system
- Don't try to force people to use a specific programming style
- No implicit violations of the static type system
- Provide as good support for user-defined types as for built-in types
- Leave no room for a lower-level language below C++ (except assembler)
- What you don't use, you don't pay for (zero-overhead rule)
- If in doubt, provide means for manual control
The differences relative to C obviously goes beyond object-oriented programming. Despite the lingering impression that C++ is just a set of extensions to C, it has for a long time been its own language, adding a strict type system (compared to C's weak type system at that time), more powerful programming paradigms, and features not found in C. Its compatibility with C can therefore be seen more as coincidence, with C being the right language at the right time to be used as a foundation.
The problem with Simula at the time was that it was too slow for general use, and BCPL was too low-level. C, being a relatively new language at the time, provided the right middle ground between features and performance.