Clause 26: Delay the occurrence of variable definitions whenever possible
std::string Encryptpassword (conststd::string &password)
{
std::string encrypted;
Encrypted=password;
Encrypt (encrypted);
return encrypted;
}
This definition is initialized encrypted the cost is a constructor and an assignment function. If you use the following method:
std::string encryptpassword (conststd::string & password)
{
std::string encrypted (password);
Encrypt (encrypted);
return encrypted;
}
Delaying the definition of variables as much as possible avoids not only constructing non-essential objects, but also avoiding meaningless default construction behavior.
N defer the occurrence of variable definitions whenever possible. This can increase the clarity of the program and improve the efficiency of the program.
Clause 27: Try to do less transformational action
n if possible, avoid transformation, especially in the efficiency-focused code to avoid dynamic_cast. If you have a design that requires transformational action, try to develop an alternative design that doesn't need to be transformed.
N If transformation is necessary, try to hide it behind a function. The client can then invoke the function without having to put the transformation into their own code.
n rather use the new transformation of C + +, do not use legacy conversions. The former is very easy to identify, but also a comparative necromancy.
Clause 28: Avoid returning handles points to the inner component of the object
Consider the definition of the following class:
Class guiobject{...}
Const Rectangle BoundingBox (const guiobject&obj);
It is possible for customers to use this function:
Guiobject *pgo;
Const Point *pupperleft=& (BoundingBox (*PGO). Upperleft ());
The above code assignment number returns the temporary Temp object to the right, and then the Temp object is released, which is Pupperleft will become overhanging (dangling)!
N Avoid returning handles to the inside of the object, adhering to this clause increases encapsulation, helps the const member function behave like a const, and minimizes the likelihood that the dangling handles will occur.
Article 29: It is worthwhile to work for exceptional safety
The exception security function provides one of three guarantees:
Basic Guarantee: If an exception is thrown, anything inside the program remains in a valid state. No objects or data structures will be destroyed.
Strongly GUARANTEE: If the exception is thrown, the program state does not change, call such a function need to have such a cognition: if the function succeeds, is completely successful, if the function fails, the program will revert to the state before calling the function.
No-throw guarantee: Promises never throw exceptions, because they are always able to accomplish the functionality they originally promised. All operations acting on the built-in type provide no-throw guarantees.
Article 30: A thorough understanding of the inside and outside of inlining
Limiting most inlining to small, frequently-called functions makes future debugging and binary upgrades easier, and minimizes potential code bloat, maximizing the chances of a program's speed increase.
Do not declare them as inline just because they appear in the header file.
Article 31: Minimizing compilation dependencies between files
n Do not use objects if you use the object's reference or pointer to complete the task
n if possible, replace class definition with class declaration
N provides different header files for declarations and definitions
clause 32: Determine your public inheritance mold out is-a relationship
Public inheritance means is-a, and everything that applies to baseclasses must also apply to derived classess, because each derived class object is also a base object.
Article 33: Avoid hiding the inherited name
Names within a derived class will obscure names within the base class, which is never expected under public inheritance.
N to let the masked name see the daylight, you can use a using declaration or a transfer function.
Article 34: Differentiating between interface inheritance and implementation inheritance
N interface inheritance differs from implementation inheritance, where the derived class always inherits the interface of the base class, under public inheritance.
N Pure virtual function specifies interface inheritance only
n Non-pure virtual functions Specify interface inheritance and default implementation inheritance.
n non-virtual functions specifically specify interface inheritance and enforce inheritance
Article 35: Consider alternatives other than virtual functions
Article 36: Never redefine inherited non-virtual functions
Public inheritance, using everything with the base class object, also applies to derived class objects, because each derived class object is a base class object, and the derived class must inherit the interface and implementation of the non-virtual function
Article 37: Never redefine inherited default parameter values
Consider the following classes:
Class Shape
{
Public
Enumshapecolor{red,green,blue};
Virtualvoid Draw (Shapecolor color=red) const = 0;
};
Class Rectangle:public Shape
{
Public
Virtualvoid Draw (Shapecolor color=green) const;
};
If you define the following variables:
Shape *p=new Rectangle;
P->draw (); This line is actually called rectangle::d Raw (shape::red)
The virtual function is dynamic bound, and the default parameter value is static binding, meaning that you may invoke a virtual function defined in a derived class, but use the base class as the default parameter value that it specifies.
Article 38: By compounding the mold out of the has-a or according to something to achieve
Consider implementing a set container, and if you use a linked list, you can define the class as follows:
Class set
{
Public
Voidinsert (const t& Item);
Voidremove (const t&item);
.....
Private
std::list<t>rep;
};
Here the set and list are has-a relationships.
The meaning of the n compound is completely different from the public inheritance.
N in the application domain, compounding means has-a. In implementing a domain, compounding means realizing it according to something.
Clause 39: Use private inheritance wisely and prudently
Consider a blank class:
Class empty{};
Class Holdsanint
{
Private
Intx
Emptye;
};
Then sizeof (holdsanint) >sizeof (int), because the empty class's Object E also occupies the memory size.
Use the following alternative implementations:
Class Holdsanint:private Empty
{
Private
Intx
};
Then sizeof (holdsanint) ==4;
Private inheritance, which makes the blank base class most optimized, reduces the size of the derived class object.
n Private inheritance means the realization of something according to the object.
Unlike N and composite, private inheritance can cause empty base class optimizations, which can be important for library developers working on minimizing the size of objects.
Article 40: Use multiple inheritance wisely and prudently
Those classes that use virtual inheritance often produce objects that are larger than those that use non-virtual inheritance, and that accessing member variables of a virtual base class is slower than accessing a member variable of a non-virtual base class. The details vary by compiler, but the basic focus is clear, and you have to pay for the virtual inheritance.
"Effective C + +" Reading notes 3