My favorite C++ books are from Scott Meyers, Effective C++ series. The first item in Effective C++, 3rd Edition is titled View C++ as a federation of languages. I took note of this suggestion the first, and each successive time I read through this book. I thought of this as a fresh way to view the breadth of diverse features and ways to apply the C++ language. However, the more I explore, learn, write and teach about the language, the more I believe this is such a profound piece of advice to help developers write the most maintainable code possible.
This observation has led me to form two conclusions, which are generally taken for granted and often overlooked.
- Always revisit what you have learned. You may recognize something based on your new experiences.
- The relative importance of your knowledge changes as your task changes. Therefore, use the advice of the first item to discover if there is something new to help you.
Collection of Languages
The advice from the item recognizes that there are actually four sub-languages contained within the C++ grammar. Each sub-language is capable of fulfilling different needs of your program. The needs are fulfilled in different ways, which possibly makes one of the sub-languages more suitable to solve a problem than others.
These features have a different set of rules to work effectively with the sub-language. Here is a quick overview of what Scott has identified, However, if you want the full description and details, support this author and buy this excellent book. I would actually go so far as to further group the items into two sub-groups. You will see below.
Consider an instance of an object that we will call, C. This object will accept a sequence of commands and output a program that can be executed for the target machine. This object type C also supports the post-increment operator. You can pass in the commands as previously noted, not only will you have the same program that can be executed, but you will also have an improved version of the object that is more capable. This is the first grouping of sub-languages. There happens to be only one sub-language in this group.
The Venerable Language of C
The roots of C++ originated from C. C's grammar uses the imperative/procedural development style. Generally all of the rules that apply to C, can be used in C++. In my development experience this is the style that is mostly used in C++ programs. Ironically, this usage matches the name of the language and how the post-increment operator behaves. There are only a few enhancements that exist in this portion of the language that should be considered when using C++ like a better form C.
Now consider the same instance of the object called, C. This object type C also supports the pre-increment operator. This will first ensure the enhanced version of command processing is used when processing the input commands to generate the output program to be executed. This group of sub-languages contains three distinct sub-languages that represent the enhancements available in C++ compared to C.
C with Objects
This sub-language contains the set of rules that are most well known for C++. This portion of the language provides the class definitions and object instances. Classic object-oriented development concepts such as encapsulation, data abstraction and polymorphism are utilized in this portion of the language. This sub-language has the most in common with other object-oriented languages. When migrating to C++ from another object-oriented language, this portion should be the easiest to grasp.
The C++ Standard Library
The Standard Template Library (STL), or actually now called The C++ Standard Library is a second sub-language to consider in this enhanced grouping of the language. STL is designed as a generic set of objects that are extremely versatile. The library contains utility objects, data containers, algorithms. With the latest official release of the C++ standard, C++ 11, there are even more generic constructs that help provide OS abstraction constructs for facilities such as time, threads, and synchronization.
The last sub-language to consider is the use of C++ templates to create Template Meta-Programs. These are programs that are written with the generic template constructs, and primarily compiled, then executed by the compiler itself. The result calculated by the compiler is then encoded into the output runtime application. This sub-language differs drastically from the other three types because these programs are developed with a functional style. This means that program state does not exist, and therefore programming by side-effects is largely eliminated. For more details on Template Meta-Programming you can read an introduction in my previous post.
What is the significance or value of thinking of C++ as these sub-languages? C++ is such a complex language that is more versatile than any other out there. The broad set of features, development styles, and ways to apply the language make it simple enough to pick up, but difficult to master. I believe I am extremely well versed in this language, and it constantly surprises me what it is capable of. The ways in which I can accomplish a complex task with such elegance, as well as the many ways that I can be bitten when I make such a simple mistake (as much as I would like to believe that I do not make mistakes).
It is important to continue to learn, especially in this field. Revisit the reference texts in which you have found value. I would also suggest skimming books that you thought were rubbish the first time you read them. There may be something new to learn, or your newer experiences may allow you to recognize something valuable that you did not recognize the first time.
C++ is a versatile language, in part because of its rich set of features and multiple programming paradigms possible with this language. The versatility and many different ways that are possible to solve the same problem sometimes interferes with our ability to solve a problem cleanly. It is possible to think of C++ as a set of four different languages that can be used to solve a problem within the same language. Each sub-language has its own set of features, rules, and excels at solving different types of problems. Learn when to use each of the different paradigms. There is great value in knowing how to identify the best to use to solve a problem, and to use that tool effectively to create the solution.