Static is a common modifier in C ++. It is used to control the storage and visibility of variables. Next I will talk about the reason and role of static modifiers, the essence of the static modifier is comprehensively analyzed.
Static:
I. Control Storage Methods:
Static is introduced to inform the compiler that the variables are stored inProgramInstead of stack space.
1. Cause: when the program executes the variable defined in the function to its definition, the compiler allocates space for it on the stack, the space allocated by the function on the stack is released at the end of the function execution. This creates a problem: If you want to save the value of this variable in the function to the next call, how to implement it?
The easiest way to think of is to define a global variable, but defining a global variable has many disadvantages, the most obvious drawback is that the access range of the variable is broken (so that the variables defined in this function are not controlled by this function ).
2. Solution: Therefore, static is introduced in C ++ to modify the variable, which can instruct the compiler to save the variable in the static storage area of the program, this achieves the goal and keeps the access range of this variable unchanged.
Ii. control visibility and connection type:
Static also has a function, which limits the visible scope of the variable to the compilation unit and makes it an internal connection. In this case, its antonym is "extern ".
Static analysis summary: static always changes the storage form of variables or objects to static storage, and the connection mode to internal connections. For local variables (internal connections already exist ), it only changes the storage mode. For global variables (which are already in static storage), it only changes the connection type.
Static member in the class:
I. Causes and functions:
1. Interaction between objects in a class is required, that is, a data object must serve the entire class rather than a certain object.
2. At the same time, we strive not to undermine the encapsulation of the class, that is, this member is required to be hidden inside the class and invisible to the outside world.
The static member of the class meets the preceding requirements because it has the following features: it has an independent storage zone and belongs to the entire class.
2. Note:
1. for static data members, the connector ensures that it has a single external definition. Static data members are initialized sequentially according to the sequence in which they appear. Note that when static members are nested, make sure that the nested members have already been initialized. The order of cancellation is the reverse order of initialization.
2. The static member function of the class belongs to the entire class rather than the class object, so it does not have the this pointer, which leads to the ability to only compile static data and static member functions of the class.
Const is a type modifier commonly used in C ++, But I found at work that many people only take it for granted. In this way, sometimes they use the correct, however, in some subtle occasions, we are not so lucky. The essence is mostly because we have not figured out the source. Therefore, in this article, I will analyze Const. Trace its source and investigate its essence, hoping to help you understand Const. Based on the undertaking relationship of thinking, this article will be divided into the following parts.
Why is const introduced in C ++?
What is the purpose of the C ++ initiator to introduce (or retain) the const keyword ?, This is an interesting and useful topic and is helpful for understanding Const.
1. as we all know, C ++ has a strict type compilation system, which allows many errors of C ++ programs to be found in the compilation stage, greatly reducing the error rate, it has also become an outstanding advantage in comparison with C ++.
2. A common preprocessing command # define variablename variablevalue in C can be easily used for value substitution. This value substitution has at least three advantages:
The first is to avoid the appearance of numbers with vague meanings, so that the program semantics is fluent and clear, as shown in the following example:
# Define user_num_max 107 avoids the confusion caused by using 107 directly.
Second, you can easily adjust and modify parameters. In the preceding example, when the number of people changes from 107 to 201, you can modify the parameters here,
Third, it improves the execution efficiency of the program. Because the pre-compiler is used for value substitution, it does not need to allocate storage space for these constants, so the execution efficiency is high.
In view of the above advantages, the use of such predefined commands is everywhere in the program.
3. Speaking of this, you may be confused about the relationship between the first and second points and Const ?, OK. Proceed to the next step.
It seems that:
The pre-processing statement has many advantages, but it has a fatal disadvantage, that is, the pre-processing statement is only a replacement of simple values and lacks a type detection mechanism. In this way, the pre-processing statement cannot enjoy the advantage of strict C ++ type checks, which may cause a series of errors.
4. Now, the first stage has come to the conclusion:
Conclusion: The initial purpose of const is to replace precompiled commands, eliminate its disadvantages, and inherit its advantages.
Now its form is changed:
Const datatype variablename = variablevalue;
Why can const replace predefined statements?
What is the magical power of const so that it can shake its arm to replace the predefined statement?
1. First, the constant value modified by const is non-mutable, which is the basis for replacing predefine statements.
2. Second, it is obvious that it can also avoid the appearance of numbers with vague meanings, and it is also convenient to adjust and modify parameters.
3. Third,C ++ compilers do not usually allocate storage space for common const constants, but store them in the symbol table.,This makes it a constant during compilation, without the storage and read memory operations.To make it highly efficient. At the same time, this is also an important basis for it to replace predefine statements. Here, I would like to mention why this is also the basis for it to replace the pre-defined statements, because the compiler will not read the stored content, if the compiler allocates storage space for const, it cannot be a constant during compilation.
4. Finally, the const definition is like a normal variable definition. It will be checked by the compiler for its type, eliminating the hidden danger of predefine statements.
Classification of const usage
1. const is used for Pointer Analysis in two cases:
Const int * A; // a variable, * a variable. This method is also correct: int const *;
Int * const A; // A is not variable, * A is variable
Analysis: const is a type modifier that is left-bound. It is the type Modifier on its left and a type modifier. Therefore, int const is limited to * a, not limited to. Int * const limits a, not *.
2. Transfer and return values
(1) const limits the passing value parameters of the function:
Void fun (const int var );
Analysis: The preceding statement specifies that parameters cannot be changed in the function body. According to the characteristics of value transfer, the changes of VaR in the function body do not affect the function exterior. Therefore, this limitation has nothing to do with the function user and is only related to the function writer.
Conclusion: It is best to limit the internal function to block external callers to avoid confusion. The following code can be rewritten:
Void fun (INT var ){
Const Int & varalias = var;
Varalias ....
.....
}
(2). Const limits the return value of the function:
Const int fun1 ();
Const myclass fun2 ();
Analysis: The preceding statement limits that the return value of a function cannot be updated. When the function returns an internal type (such as fun1), it is already a constant value, of course, it cannot be updated by value assignment (that is, as the left value). Therefore,At this time, const is meaningless. It is best to remove it.To avoid confusion.
When the function returns a custom type (such as fun2), this type still contains variable members that can be assigned values. Const indicates that it cannot be left, that is, it cannot be assigned values, cannot be modified. so it makes sense.
If you do not add const: myclass fun2 ();
It is possible to write: fun2 () = OBJ; // although ugly, it can indeed be compiled through
3. Transfer and return address (pointer or reference): This is the most common case. We can see from the characteristics of address variables that the appropriate use of const is significant.
(1) const limits the passing pointer or reference parameter of a function:
Void fun (const int * pvar );
Void fun (const Int & rval );
Analysis: the above Code passes the address, so the variable to which the parameter points in the function is likely to be changed. Using const can effectively limit that the parameter cannot be changed in the function body.
Conclusion: Except for the variables that need to be pointed to by pointer parameters in the function, it is good to add const to the parameters passed by the address.
(2). Const limits the return value of the function:
Const int * fun1 ();
Const Int & fun1 ();
// Without const, fun1 () can be changed as the left Value
Const myclass * fun2 ();
Const myclass & fun2 ();
Analysis: Generally, when using a reference as the return type, note the following:
Format: type identifier & function name (parameter list and type description) {// function body}
Benefit: do not generate a copy of the returned value in the memory. (Note: For this reason, it is not advisable to return a reference to a local variable. As the survival of the local variable ends, the corresponding reference will also become invalid, resulting in a runtime error!
Note:
(1) References to local variables cannot be returned. For details, refer to item 31 of Objective C ++ [1. The main reason is that local variables will be destroyed after the function returns, so the returned reference becomes a reference of "no finger", and the program enters the unknown state.
(2)You cannot return a reference to the memory allocated by the new function.. For details, refer to item 31 of Objective C ++ [1. Although there is no passive destruction of local variables, this situation (returning a reference to the memory allocated by the new function) faces other embarrassing situations. For example, if a reference returned by a function only appears as a temporary variable and is not assigned to an actual variable, the space pointed to by the reference (allocated by new) cannot be released, cause memory leak.
(3) You can return a reference to a class member, but it is best to use Const. This principle can be referred to item 30 of Objective C ++ [1. The main reason is that when an object attribute is associated with a business rule, its value assignment is often related to some other attributes or the state of the object, therefore, it is necessary to encapsulate the value assignment operation in a business rule. If other objects can obtain the non-constant reference (or pointer) of this attribute, a simple value assignment to this attribute will damage the integrity of business rules.
(4) The function of declaring the returned value of stream operator overload as "Reference:
Stream operators <and>, which are often used consecutively, for example, cout <"hello" <Endl; therefore, the return value of these two operators should be a stream reference that still supports these two operators. Other optional solutions include returning a stream object and returning a stream object pointer. However, for a returned Stream object, the program must re-(copy) to construct a new stream object. That is to say, two consecutive <operators are actually for different objects! This is unacceptable. If a stream pointer is returned, the <operator cannot be used consecutively. Therefore, returning a stream object reference is the only choice. This unique choice is critical. It illustrates the importance of reference and is irreplaceable. Maybe this is why the concept is introduced in C ++. Value assignment operator =. This operator can be used continuously like a stream operator, for example, x = J = 10; or (x = 10) = 100; the return value of the value assignment operator must be a left value, so that the value can be assigned. Therefore, it is referenced as the only return value choice of this operator.
Example 3
# I nclude <iostream. h>
Int & put (int n );
Int Vals [10];
Int error =-1;
Void main ()
{
Put (0) = 10; // use the put (0) function value as the left value, equivalent to Vals [0] = 10;
Put (9) = 20; // use the put (9) function value as the left value, which is equivalent to Vals [9] = 20;
Cout <Vals [0];
Cout <Vals [9];
}
Int & put (int n)
{
If (n> = 0 & n <= 9) return Vals [N];
Else {cout <"subscript error"; Return Error ;}
}
(5) among other operators, the reference: +-*/four Arithmetic Operators cannot be returned. They cannot return references. The Objective C ++ [1] item23 discusses this issue in detail. The main reason is that these four operators do not have side effect. Therefore, they must construct an object as the return value. Optional solutions include: returning an object and returning a reference to a local variable, returns the reference of a newly assigned object and a static object reference. According to the preceding three rules that reference the returned value, both the 2nd and 3 schemes are rejected. Static object reference is caused by errors because (a + B) = (C + D) is always true. Therefore, only one object is returned.
5. Const qualified class member functions:
Class classname {
Public:
Int fun () const;
.....
}
Note: This post-const form is a provision to avoid confusion. Use const in the declaration and definition of this function, because const has become part of the type information.
Ability to obtain: constant objects can be operated.
Capacity Loss: you cannot modify the data members of a class or call other functions that are not const in a function.
In this article, I am not talking much about const, because I don't want to turn it into a C ++ textbook. I just want to elaborate on its essence and usage in detail. I will try to explain it in detail, because I hope to express some of my thoughts in a very relaxed and casual atmosphere. After all, programming is also part of a relaxed and happy life. Sometimes, you may wonder that the world is so beautiful.
After talking about const in the previous article, let's talk about the keyword inline.ArticleIn this position, it is because the inline keyword is introduced for a very similar reason as Const. The following sections are described as follows.
The reason why the inline keyword is introduced in C ++:
The Inline keyword is used to define an inline function of a class. The main reason for introducing it is to use it to replace the macro definition in expression form in C.
An example of macro definition in expression form:
# Define expressionname (var1, var2) (var1 + var2) * (var1-var2)
Why should we replace this form? Let me say:
1. First, let's talk about the reasons for using this macro definition in C,C LanguageIs a very efficient language. This macro is defined in the form and used as a function, but it is implemented using a pre-processor without the parameter pressure stack,CodeGeneration and other operations, so the efficiency is very high, which is one of the main reasons it is used in C.
2. this macro definition is similar to a function in form, but when using it, it only performs simple replacement in the pre-processor symbol table, so it cannot detect the parameter validity, therefore, the C ++ compiler cannot strictly check the type, and its return value cannot be forcibly converted to a suitable type for conversion, its use has a series of risks and limitations.
3. the Class and Class access control are introduced in C ++. In this way, if an operation or expression involves the protection or private member of the class, you cannot use this macro definition (because you cannot place this pointer in a proper position ).
4. The purpose of inline is to replace the macro definition of this expression form. It eliminates its shortcomings and inherits its advantages.
Why does inline replace the definition of expression format?
1-3 points are described as follows:
1. inline functions of classes defined by inline. The code of the functions is put into the symbol table and replaced directly during use (expanded like a macro), without the call overhead and high efficiency.
2. Obviously, the inline function of a class is also a real function. When the compiler calls an inline function, it first checks its parameter type to ensure that the call is correct. Then perform a series of related checks, just like treating any real function. This eliminates its hidden dangers and limitations.
3. inline can be used as a member function of a class. Of course, you can use the protected member and private member of the class.
When to use the inline function:
First, you can use the inline function to completely replace the macro definition in expression form.
In addition, it should be noted that inline functions are generally used only when the function content is very simple. This is because the code of inline functions is expanded wherever it is called. If the function is too complex, the consequence of code expansion is likely to be greater than the benefits of efficiency improvement. The most important use of inline functions is for class access functions.
How to Use the class inline function:
Here is a brief introduction to the use of inline:
1. Define this function in the class:
Class classname {
.....
....
Getwidth () {return m_lpicwidth;}; // if it is directly defined in the class, you can skip the inline modifier.
....
....
}
2. declare in the class and define it outside the class:
Class classname {
.....
....
Getwidth (); // if it is defined directly in the class, it can be modified without using inline.
....
....
}
Inline getwidth (){
Return m_lpicwidth;
}
In this article, we talk about a special function, the inline function of the class, which is similar to the const in terms of its source and characteristics. It can be combined with the const. In addition, many of my friends recently interacted with me via mail, talked about many issues and gave me a lot of inspiration. I would like to express my gratitude here.
The basic idea of object-oriented programming is to use a program to simulate the world, which makes its various fundamental features very user-friendly, such as encapsulation, inheritance, polymorphism, etc, the virtual function is the main implementation of polymorphism in C ++. To achieve polymorphism, the C ++ compiler also revolutionizes dynamic binding (or late binding.
Virtual functions are also the key to MFC programming. There are two main methods for MFC programming: one is to respond to various messages for corresponding message processing. Second, reload and rewrite virtual functions to meet certain requirements or change some default processing of the system.
The role of a virtual function is so important. It is very helpful for us to understand and understand it. Let me hear it.
Implementation Process Analysis of polymorphism and dynamic binding
I. basic information (for space restrictions, refer to the corresponding C ++ books ):
1. Polymorphism: Use the pointer of the base class to dynamically call the features of functions in its derived class.
2. Dynamic Association: in the running stage, the function call is connected to the corresponding function body, also known as runtime association or late binding.
Ii. Process description:
1. the compiler finds that a class contains virtual functions. The Compiler immediately generates a virtual function table vtable for this class (the vtable is analyzed later ). Each table item in the virtual function table is a pointer to the corresponding virtual function.
2. the compiler implicitly inserts a pointer vptr in this class (for VC compiler, It is inserted at the first position of the class ).
There is a way for you to perceive the existence of this implicit pointer, although you cannot directly see it in the class, however, you can compare the class size when there is a virtual function and the class size when there is no virtual function. You can find that this pointer does exist.
Class cnovirtualfun
{
PRIVATE:
Long lmember;
Public:
Long getmembervalue ();
} Class chavevirtualfun
{
PRIVATE:
Long lmember;
Public:
Virtual long getmembervalue ();
}
Cnovirtualfun OBJ;
Sizeof (OBJ)-> = 4;
Chavevirtualfun OBJ;
Sizeof (OBJ)-> = 8;
3. When calling such constructor, In the constructor of the class, the compiler will implicitly execute the code associated with vptr and vtable, and direct vptr to the corresponding vtable. This associates the class with the vtable of this class.
4. When calling the class constructor, the pointer to the base class has now become the this pointer to the specific class, so that the correct vtable can be obtained by using this pointer, this achieves polymorphism. In this case, we can truly connect to the function body, which is dynamic Association.
Iii. vtable analysis:
Analysis 1: The virtual function table contains the addresses of all the virtual functions of this class and its parent class. If it does not reload the virtual function of the parent class, the corresponding table item in vtable points to this function of the parent class. Otherwise, point to the function after the overload.
Analysis 2: After a virtual function is inherited, it is still a virtual function. The virtual function is strictly ordered in the vtable according to the order in which it appears. Therefore, the determined virtual function corresponds to a fixed position N in the vtable, N is a constant determined during compilation. Therefore, add the corresponding N to vptr to obtain the corresponding function entry address.
Iv. assembly code for the compiler to call a virtual function (refer to think in C ++ ):
Push funparam; pressure the function parameter stack first
Push Si; press this pointer to the stack to ensure the operation on the current class
MoV BX, word PTR [Si]; because the VC ++ compiler places vptr on the first position of the class, the BX is vptr
Call word PTR [bx + N]; call a virtual function. N = Location of the called virtual function in the corresponding vtable
Pure virtual functions:
I. Reasons for introduction:
1. To facilitate the use of polymorphism, we often need to define virtual functions in the base class.
2. In many cases, it is unreasonable for the base class to generate objects. For example, an animal can be derived from sub-classes such as tigers and peacocks as a base class, but the object generated by the animal itself is obviously unreasonable.
To solve the above problem, the concept of pure virtual function is introduced, and the function is defined as a pure virtual function (method: Virtual returntype function () = 0 ;), the compiler requires that the class must be overloaded to implement polymorphism. Classes that contain pure virtual functions are called abstract classes and cannot generate objects. In this way, the above two problems are well solved.
Ii. essence of pure virtual functions:
1. If the class contains a pure virtual function, its vtable table is incomplete and there is a blank space. Therefore, an object cannot be generated (the compiler absolutely does not allow the possibility of calling a function that does not exist ). In its derived class, unless this function is reloaded, The vtable table of this derived class is also incomplete and the object cannot be generated, that is, it also becomes a pure virtual base class.
Virtual functions and constructor and destructor:
1. the constructor itself cannot be a virtual function, and the virtual mechanism does not work in the constructor (the virtual function in the constructor only calls its local version ).
Think about it. Using the virtual mechanism in the base class constructor may call the subclass. At this time, the subclass (which should be the parent class) has not yet been generated. What are the consequences !?.
2. The Destructor itself often requires virtual functions, but the virtual mechanism does not work in the destructor.
If a virtual function is used in the class, the Destructor must be a virtual function. For example, if a virtual mechanism is used to call Delete, there is no virtual destructor, how can we ensure that the delete object is the object you want to delete.
The virtual mechanism cannot take effect in the destructor, because it may cause the issue of calling virtual functions of classes that have been deleted.
Object slicing:
When the child class is mapped to the parent class, the vtable of the Child class is completely changed to the vtable of the parent class. This is the object slice.
Cause: When ing up, the interface will narrow down, And the compiler absolutely cannot call a function that does not exist. Therefore, the portal of the new derived virtual function in the subclass is forcibly cut out in the vtable.
Disadvantages of using virtual functions
There are a lot of advantages. Now let's talk about the disadvantages. The main disadvantage of virtual functions is that the execution efficiency is low. Let's take a look at the implementation process of polymorphism caused by virtual functions, and you will be able to understand the reasons.