Document directory
- Entry 7: declare virtual destructor for the polymorphism base class
- Clause 9: Do not call virtual functions in constructors or destructor
- Terms 13 ~ 15. manage resources through objects
- Cla23: Replace the member function with the non-member non-friend function.
- Clause 30: inline functions
Valid C ++ has read several articles, which are basically the most basic principles for using C ++. Many entries have been regarded as standards. A recent review will briefly record some sensible knowledge points.
Entry 7: declare virtual destructor for the polymorphism base class
If a class is used in a multi-state mode, a virtual dtor is required. In this way, relevant objects can be correctly destroyed. However, it is also wrong to provide virtual destructor roughly for all classes, which leads to low efficiency, even the "portability" issue (the Implementation Details of virtual functions are determined by the compiler. Whether a class contains virtual functions affects the memory layout of the class instance ). Therefore, when designing a class, consider whether it may be inherited. One experience is that "only when a class contains a virtual function can its destructor be declared as virtual".
In turn, if the destructor of a class is non-virtual (or is not declared at all), it usually means that this class is not designed as a base class. But what is really dangerous is that "using polymorphism", inheritance does not mean polymorphism, so if you are sure you will not use a class inheritance system in polymorphism mode, then the base class has no virtual destructor and it does not matter. But I think it is better to avoid it.
Clause 9: Do not call virtual functions in constructors or destructor
Sometimes we want the base class constructor to distinguish whether a base class object is being constructed or a derived class object is being constructed and execute different code. Therefore, we may declare a virtual function in the base class to encapsulate the code and then call the virtual function in the constructor.
But in fact, C ++ does not support this. If you call a virtual function in the base class constructor, the virtual function implementation of the base class is always called. This is because the Member of the subclass has not yet been initialized. Calling the subclass function may lead to undefined behavior. Therefore, C ++ eliminates this possibility. In fact, in the base class constructor, If you query the dynamic type of the current object, the result must also be the base class type.
The same applies to destructor. We should not only call virtual functions directly, but also indirectly.
If we really need the function described in the first section, we can consider adding a parameter to the base class constructor. The initialization class table of the derived class can customize different behaviors by providing parameters. If this still does not meet your needs, consider changing the design.
Terms 13 ~ 15. manage resources through objects
Using objects to manage resources provides many benefits, making full use of C ++'s support for objects: Construction, survival, and analysis to ensure the security of resource usage. You can use simple objects such as auto_ptr to manage a single heap object resource. You may need to abstract one to encapsulate the resource. Such a class is a resource management class with a single function: holding resources. Separating resource management and usage makes the Code have a better style and exception security.
We generally follow the principle of raiI and resouce acquire in initialization, that is, to obtain resources in the initialization structure of the resource management class and destroy resources in the destructor.
Pay special attention to the copy behavior of the resource management class. You may not be allowed to copy or reference the Count copy.
Some APIs may require the original resource pointer. You can provide implicit type conversion or the displayed get function to provide the original type. But the latter is safer.
Cla23: Replace the member function with the non-member non-friend function.
If a member function does not require a private member of the member class, consider replacing it with a non-member non-friend method. Encapsulation is taken into consideration. Encapsulation means that less code can be a private member of the callback class, the better the encapsulation. This is contrary to the design idea of "Binding data and operation data methods together", which is an object-oriented misunderstanding.
Providing a none-member none-friend function can improve our encapsulation. Generally, a namespace or a class containing only static methods ** utility is provided to organize such functional methods together. This frame is similar to the previous idea of using classes to manage resources. Its fundamental idea is "single function principle ". This class provides basic functions. As for combining some functions into a method to facilitate the user, you can use another class ** utility.
In the library design, such as the C ++ standard library, this design is very common. Different functional methods can be organized into different header files and namespaces to reduce compilation dependencies.
But in the application design, we occasionally need one or two of these methods. I think it is better to use the memeber function directly.
Clause 30: inline functions
If there is no evidence that a function is called in large numbers, resulting in efficiency problems, do not use inline. Inline is always accompanied by some risks. For example, constructor and destructor are hardly correct if declared as inline, because the compiler may insert some code that you do not know in constructor and destructor.