Success is not final, failure is not fatal: it is the courage to continue that counts.
Winston Churchill
This book arose as a result of my fascination with computers and programming with the C++ language. It is also a result of my over 20 years of teaching the basics of computer science and particularly the C++ language to the students of the faculties of electrical engineering as well as mechanical engineering and robotics at AGH University of Science and Technology in Krakow, Poland. I have also worked as a programmer and consultant to several companies, becoming a senior software engineer and software designer, and have led groups of programmers and served as a teacher for younger colleagues.
Learning programming with a computer language is and should be fun, but learning it well can be difficult. Teaching C++ is also much more challenging than it was a decade ago. The language has grown up significantly and provided new exciting features, which we would like to understand and use to increase our productivity. As of the time of writing, C++20 will be released soon. In the book, we use many features of C++17, as well as show some of C++20. On the other hand, in many cases, it is also good to know at least some of the old features as well, since these are ubiquitous in many software projects, libraries, frameworks, etc. For example, once I was working on a C++ project for video processing. While adjusting one of the versions of the JPEG IO libraries, I discovered memory leaks. Although the whole project was in modern C++, I had to chase a bug in the old C code. It took me a while, but then I was able to fix the problem quickly.
The next problem is that the code we encounter in our daily work is different than what we learn from our courses. Why? There are many reasons. One is legacy code, which is just a different way of saying that the process of writing code usually is long and carries on for years. Moreover, even small projects tend to become large, and they can become huge after years of development. Also, the code is written by different programmers having different levels of understanding, as well as different levels of experience and senses of humor. For example, one of my programmer colleagues started each of his new sources with a poem. As a result, programmers must not only understand, maintain, and debug software as it is, but sometimes also read poems. This is what creates a discrepancy between the nice, polished code snippets presented in classes as compared to “real stuff.” What skills are necessary to become a successful programmer, then?
Why did I write this book, when there are so many programming Internet sites, discussion lists, special interest groups, code examples, and online books devoted to software development? Although all of these frequently are great and highly useful as instant references, it is sometimes difficult to find places or sources that lead us step-by-step through the learning process. It is even more difficult to find good examples that teach key programming techniques and at the same time are short, practical, and meaningful. So, I would like to share with you the synergy of theory descriptions underpinned with project examples that I have collected during my years of programming and teaching.
Let us now look at a short overview of the main subject of this book. The C++ programming language is one of the most influential, commonly used, and fascinating languages, initially developed by Bjarne Stroustrup in the 1980s. In the last decade, it has undergone vast and fundamental changes. The roots of C++ are in the C and Simula programming languages (Stroustrup B., Evolving a language 2007) (Stroustrup B., The C++ Programming Language 2013). As we will see, basic constructions such as expressions and statements, for instance, are almost the same for the two. Also, for years, all C++ compilers have been able to swiftly compile C code. C is the language that greatly influenced our technological revolution, proving to be a key tool in the development of the highly influential Unix operating system, followed by all the other OSs, including Windows, Linux, and Android. Due to its multiplatform compatibility and light footprint, C is still used in embedded systems, field-programmable gate array (FPGA) devices, and graphics cards (graphics processing units GPUs), as well as in code acceleration on parallel platforms. There are also tons of libraries written with C and still in use, such as those with efficient numerical algorithms or for image processing, to name a few. Simula, on the other hand, was one of the first languages equipped with classes, and it fostered the methodology of object-oriented software development. This became a cornerstone of the majority of technological endeavors. Hence, paraphrasing, C++ inherited from these two: from C in public, and from Simula in private.
Although there are many programming languages, learning C++ is worth the effort, especially for people planning to work or already involved in any kind of computer programming, especially for systems and performance. To grasp the main features of C++, it is sufficient to read this book; we will explore them in depth. However, as an introduction here, let us briefly list the most characteristic ones, as follows.
auto
keyword has greatly simplified the use of types and simply lets us save on typingauto
, lambdas lead to more elegant code and increased productivitystd.::vector
class from the SL, representing a dynamically growing array of objects; it is able to store almost any object that can be automatically initializedThis is just a brief overview of the characteristics of the C++ language. In many discussions, it is said that the price we pay for all these features is language complexity, which also makes the learning curve relatively steep. That can be true, but let us remember that we do not need to learn everything at the same time. That is, paraphrasing Oprah Winfrey, when you learn C++ features, “You can have it all. Just not all at once.”
You may have also heard of the 80/20 rule, also called the Pareto principle. It says that 80% of the CPU time will be spent on 20% of the code, or that 80% of errors are caused by 20% of the code, and so on. The point is to recognize that the majority of things in life are not distributed evenly, and usually 20% of the effort will be responsible for 80% of the effect. With respect to learning C++, my impression is that, to some extent, we can apply the Pareto principle. The goal of the first two chapters of this book is just to provide the necessary basics. How many programs can be written with this knowledge? Hopefully, many. However, this does not mean the rest of the book is not important. On the contrary, the introductory parts give us a solid foundation, but the more advanced features provide the top gears we need to take full advantage of C++ and to become professional software designers and programmers. How do we achieve these goals? As in many other disciplines, the answer is practice, practice, and practice! I hope the book will help with this process.
Here are some key features of the book.
The book is intended for undergraduate and graduate students taking their first steps in computer science with the C++ programming language, as well as those who already have some programming experience but want to advance their skills. It is best suited for programming classes for students of electrical engineering and computer science, as well as similar subjects such as mechanical engineering, mechatronics, robotics, physics, mathematics, etc. However, the book can also be used by students of other subjects, as well as by programmers who want to advance their skills in modern C++. The prerequisites to use the book are modest, as follows:
The book can be used in a number of scenarios. As a whole, it best fits three or four semesters of linked courses providing an introduction to programming, OOP, and the C++ programming language in particular, as well as classes on advanced programming methods and techniques. The book can also be used in courses on operating systems and embedded systems programming, and it can serve as supplementary reading for courses on computer vision and image processing. This is how we use it at the AGH University of Science and Technology.
On the other hand, each chapter can be approached and read separately. And after being used as a tutorial, thanks to its ample summaries, tables, figures, and index, the book can be used as a reference manual for practitioners and students.
The diagram in Figure 1.1 shows the organization of the book and possible paths for reading it. The following list describes the contents of the chapters:
main
function with a very limited set of statements and operators. The ubiquitous
std::cout
and
std::cin
objects from the SL, representing output to the screen and input from the keyboard, respectively, are presented. In the last example,
std.::vector
and
std.::string
are introduced, for a dynamic array and a text string representation, respectively. Although limited, the set of C++ mechanisms introduced in this section allows us to write a fairly large group of simple programs
std::vector
and
std::string
are approached again, with a greater degree of detail. The following sections present the
auto
keyword, an introduction to some SL algorithms, structures and classes, fixed-size arrays with
std::array
, references, pointers, statements, functions (including lambda functions), tuples with
std::tuple
, and structured binding, as well as operators. Along with many small examples, three relatively simple but complete projects are presented: representation of matrices, a class to represent quadratic equations, and a project containing two custom classes for the representation and exchange of various currencies. The aim of the examples and this chapter is to teach how to properly create and use a single class with its data and function membersfor
loops, and how to measure execution time with examples of matrix multiplicationmain
function, simple arrays, unions, and C-like string representations are encountered in daily programming life. Other topics, such as linking and binary organization of C/C++ programs, graphical user interfaces (GUIs) available to C++ programs, software testing, and a programming toolchain composed of CMake, Git, and GitHub, as well as the Profiler, are also presentedAs already mentioned, the book does not need to be read linearly. The chapters are organized in such a way as to facilitate their separate use. The book's Appendix and many summaries and references can also be used independently when working on the code projects.
In addition, it is important to realize that presenting highly detailed programming topics in a linear fashion is basically impossible. Therefore, some constructions, although used in a given context, may not be well understood on first reading but are explained in later sections.
For easier navigation, a few different formats are used in this book, as follows:
The output in the terminal window (also known as the console or command line) is then presented, also on a color background, as follows:
Code on a white background is either older legacy code in C, such as that presented in Appendix A.2, or code that for some reason is not recommended to be used in C++ but is shown as part of the explanation of some phenomenon. This way, we can easily distinguish between the two types of code.
At the beginning of each code snippet is a caption, such as Listing 1.1 in the previous example. It describes the intention of the code and – if the code comes from one of the project files – includes the name of the file containing this code, in parentheses and written in italics, such as main.cpp. For better readability, long sections of code are frequently split into a number of shorter code snippets. In such cases, a caption is included only once, above the first snippet, and the line numbering continues until the end of the entire code component.
main
function is defined in lines [3–8], and lines [5, 6] contain comments, which in C++ start with double slashes
//
. To emphasize the importance of the latter, comments are in redstd::cout
object, which represents a screen, is written with a special monospaced font. On the other hand, file names – such as iostream and main.cpp – are in an italic fontstd::
prefix, as we have already seen. However, the prefix can be omitted as for example
endl
if the
using std::endl
(meaning “end-of-line”) directive is placed at the top of the code. Hence, two versions are used in the presented code, depending mostly on the context, but also on the available spaceCtrl
+
Alt
+
T
(which opens a terminal window in Linux)As alluded to previously, the book contains dozens of code examples. The learning process relies on making the code run and understanding why and what it does. So, here are some hints on how to use the code:
Modern C++ compilers are masterpieces. For instance, prior to the construction of the complete executable, a modern compiler can even precompile parts of the code; these can be then immediately executed by the compiler to compute any results obtainable at this stage, which can be then directly put into the final code to avoid computations at runtime. We will also discuss how to benefit from these features. However, if something is incorrect and the code does not compile, sometimes it is not easy to figure out the cause and, more important, how to solve it. A compiler tries to tell us precisely what is wrong. But because errors can happen everywhere and at different levels, an error message can be a real mystery. Compilers are still far from being able to tell us exactly how to get out of trouble. Maybe AI will bring new possibilities in this area. At the moment, such language features as concepts in C++20 are available. As always, some experience and contact with worldwide programming colleagues are the best resources to help.
So, what do we do if code does not compile? – Here are some hints for beginners:
error C2628: 'MonthDays' followed by 'void' is illegal (did you forget a ';'?)
.” Yes, indeed, I forgot the semicolon
;
just after a definition of the
MonthDays
structure. Adding the missing
;
fixes the problem in this case. But that was easy//
in front of a line, or by enclosing the code with
#if 0 temporarily_disabled_code #endif
directives. If the rest compiles, then narrow the disabled area, and check againswitch-case
statement can be written with
if-else
, etc. However, do not abandon non-compiling code before you find out and understand why it does not compile. It can take some time, but this way, you learn and avoid losing time in the future when you encounter a similar problem. Only after you understand what you did wrong should you consider using another or better language construction