It is very interesting for a language book to have a quick tour before everything. Actually, it is a great idea for people whose first language is not C++. People just don’t have to go through the basic things like control flows to know a language.
Generally, I have a feeling that C++’s code explain more itself. Programmers know more about what they are doing instead of checking documents for reference.
The Basics
Chapter 2 covers the very basic things (that would include control flows). First thing to note is that the introducing of namespace. Namespace in C++ seems to be clear and straightforward. What is not-so-straightforward is the name of header file/shared object library. Well, Java’s package infrastructure makes things more clear, though trying to put everything inside its structure probably is not so clever.
I didn’t expect C++ provides things like ‘auto’. (Well, not the ‘auto’ when I first use C language a few years ago.) Anyway, C++ is not a dynamic tool language. However, if you think about it, it is nothing runtime here, and you just need a compile time check. To be a real dynamic language, the thing you need is a flexible variable type (which is implemented in runtime even if you could do it in compile time) and generic programming for functions.
We finally have bools in C++!
C already have const. It was a beautiful promise that one should keep. constexpr does more than that. It calculates the value at compile time. When using constexpr as decorator of a function, it will evaluate at compile time when possible. Those function must be as simple as only having a return statement. Note that if a value is const, the compiler will assume you to keep the promise. Conclusion: Do keep your promise or you will have something unexpected.
Structs are improved. Say goodbye to the strange typedef!
Operators are functions, which they should be! Just need to have it in mind that if the value is lvalue or rvalue, to make the return type reference when necessary.
We also got a good syntax sugar for initiating fields. And a real enum class which is more than int.
C++ provides a more standard way for error handling. Exception introduced just like all of the other modern programming languages. Static assertions provide error handling on compile time.
There are some designing ideas. Invariant are restrictions applied to class definitions, and should be present in the code. If not, the functions should be independent rather than a member.
Abstract mechanism
As we can find in any articles about OOP, there is some mechanism in classes, like concrete/abstract class and class. There are some concerns under data storage since in C family you have to care more about memory, like the idea of the container. Also, note the following format for heap allocated arrays.
double *elem = new double[s]; delete[] elem;
Instead of making all functions virtual, we need to explicitly specify if a function is a virtual one. A class with at least a virtual function is called abstract class, which can not be instantiated. The mechanism behind overriding is vtbl. Usually, this is to add a 4 byte for pointer at the beginning of each object. If we want to call the virtual function in the base class, we can use scope resolution (::) operator to specify the class name, and this is called suppressed.
Constructor and destructor are called in a certain order. We don’t need to do anything for the constructor. However, for destructors, we need to make them virtual on base classes. Otherwise, only one of them is called.
An important designing idea for C++ is cautious against pointers. In C code, it is not strange for a function to return a raw pointer which points to something in heap. However, it is no longer recommended in C++. Destructors help us manage heap memory more freely. Moreover, we have unique_ptr as a smart pointer.
We need to note that “this” is a pointer, as it is in Java. Also, a const method is one that doesn’t change the object. Moreover, we can specify access-specifier when inheriting.
Copy and move. The default behavior of C++ copy is shallow copy since it just does a copy bitwise. To make it copy deeply, we just need to override operator =. Moreover, C++ provides the std::move mechanism.
std::move is a fast way to generate “right value reference”. In many cases, we don’t really need to copy the whole objects, especially when it is a container( such that copy is expensive. ) && is the mark for right value reference. When it is a parameter of a function, it (instead of the const &) can match the right value reference, to do a memory-economic behavior in the function.
If we don’t want certain behavior in the derived class, we can use the “=delete” mechanism.
class Shape{ public: //no copy Shape(const Shape&)=delete; Shape& operator=(const Shape&)=delete; //no move Shape(Shape &&)=delete; Shape& operator=(Shape &&)=delete; }
Template. Generic programming is very useful for OOP. C++ has the template grammar:
Single:
template<typename T>
Multiple:
template<typename T, typename U>
Variadic:
template<typename T, typename... Tail> void f(T head, Tail... tail){ g(head); f(tail...); }
To override the operator(), we can use it as a functional object. For instance
<typename T> class Less_than{ const T val; public: Less_than(const T &v): val(v){} bool operator()(const T &v) const {return v<val;} }