C ++ from scratch (11)
-- Knowledge about classes
Due to space limitations, this article is the next article in "C ++ from (11)", discussing polymorphism and other issues.
Virtual meanings
The middle part of this article has already introduced the meaning of virtual reality, that is, indirect acquisition, and examples show that TV channels allow people to indirectly obtain TV station frequencies. Therefore, in this sense, it is virtual, it may fail because a channel has not been properly tuned, resulting in a snowflake. The indirect advantage is that you only need to compile a piece of code (by Channel 5), and different results may occur each time you execute the Code. (today, Channel 5 is set to five in the center, it can be set to 2 in the center tomorrow, which makes the preceding program (by Channel 5) very flexible. Note that the reason why virtual reality can be flexible is that it must be achieved indirectly through "one means", for example, each channel records a frequency. However, this is not enough. There must be another piece of code that can change the results of that method (the frequency of channel recording), such as redeployment.
First look at virtual inheritance. It indirectly obtains the location of the parent class instance from the subclass instance and implements it through the Virtual class table (this is a "method "), then, you must have "another piece of code" to change the value of the virtual table to show its flexibility. First, you can write this code by yourself, but it requires that you know where the compiler places the virtual class table, and different compilers have different implementation methods, so the compatibility of the written code is very poor. C ++ certainly provides "another piece of code", that is, when a class is falsely inherited multiple times in the same class inheritance system, changes the value of the virtual class table so that the parent class instance indirectly obtained by each subclass is the same. This operation only saves memory. For example:
Struct a {long ;};
Struct B: virtual public a {long B ;}; struct C: virtual public a {long c ;};
Struct D: Public B, public c {long d ;};
Here, D has two virtual class tables inherited from B and C respectively. In the constructor of D, the compiler will write the necessary code to correctly initialize the two virtual class tables of d so that the instances of a inherited by B and the virtual class tables inherited by C are the same. one.
Look at the virtual function. Its address is indirectly obtained through the virtual function table (this is a "method"), and then the content of the virtual function table must be changed. Similarly, if you rewrite the code, the code compatibility is poor, and C ++ also provides "another piece of code". Just like above, you can enter the virtual function table in the constructor of the derived class, write the virtual function table based on the current derived class. It must fill a virtual function table with the address of the type, name, and function that is originally defined as a virtual function that matches as much as possible under the current derived class. For example:
Struct a {virtual void ABC (), BCD (float), ABC (float );};
Struct B: Public A {virtual void ABC ();};
Struct C: Public B {void ABC (float), BCD (float); Virtual float CCC (double );};
Struct D: Public c {void ABC (), ABC (float), BCD (float );};
In a: A, enter the addresses of two A: ABC and one a: BCD in the virtual function table of.
In B: B, fill B: ABC and the inherited B: BCD and B: ABC in the virtual function table of B.
In C: C, fill C: ABC, C: BCD, And the inherited C: ABC in the virtual function table of C, and add an element: C:: CCC.
In D: D, fill two D: ABC and one D: BCD and the inherited D: CCC in the virtual function table of D.
Here, d inherits from A, B, and C in sequence, and does not generate two virtual function tables because of multiple inheritance. There is only one virtual function table. Although the member functions in D are not modified by virtual, their addresses are still filled in the virtual function table in D, Because Virtual only indicates that the member functions need to obtain their addresses indirectly when using them, it has nothing to do with whether to fill in the virtual function table.
Why do TV sets use channels to indirectly obtain the frequency of TV stations? Because the frequency of the TV station is not easy to remember, and if you know a frequency, slowly adjust the capacitance value of the common harmonic capacitor to make the circuit reach that frequency efficiency is very low. For 10 groups of common harmonic circuits, the capacitance values of each group of circuits are adjusted and no longer moved. Different common harmonic circuits are switched to achieve fast conversion frequency. Therefore, the efficiency can be improved indirectly. In addition, Channel 5 is originally a central five, and later it is difficult to replace it with a central two, then the same action (by Channel 5) will produce different results, the program "by Channel 5" is very flexible.
At least we can know from the above: indirectly used to simplify operations, improve efficiency and increase flexibility. The three indirect uses mentioned here are all based on the idea that "one means" is used to achieve the purpose and another piece of code is used to achieve the purpose mentioned above. The virtual inheritance and virtual functions provided by C ++ can be used as long as they are members or virtual functions inherited by virtual inheritance ". To implement "another piece of code", we can see from the above description that it needs to be achieved by means of derivation. You can change the virtual function table by defining the same functions as the virtual function prototype declared in the parent class in the derived class, in the inheritance system of a derived class, the virtual class table can be changed only when the class that has been falsely inherited is repeated, and it only points to the instance of the same class that has been falsely inherited, it is far from convenient and flexible modification of virtual function tables. Therefore, virtual inheritance is not commonly used, while virtual functions are often used.
Virtual use
Because the implementation of "virtual" in C ++ requires the use of derivative means, while derivation is the generation type, the "virtual" is generally mapped to the indirect type, rather than the indirect implementation of the above channel through an instance (a set of common harmonic circuits. Note: The "simplified operation" refers to the complex operation of function ing, which simplifies code writing and indirectly executes the corresponding code using the address mapped by function name, virtual functions are called to present multiple execution results. "Improving Efficiency" is an algorithm improvement, that is, the channel is achieved by repeating ten sets of common harmonic circuits, and the authentic space is changed for time, it is not indirectly implemented on the type. Therefore, the "virtual" in C ++ can only increase code flexibility and simplify operations (for the three indirect advantages proposed above ).
For example, when an animal is called, different animals call different methods and make different sounds. In this case, the type of an animal requires "one means" (called) to show different effects (dogs and cats are called different), and this requires "another piece of code" to implement, that is, through derivation. That is to say, from the cat and dog classes of the class animal, you can declare "Call (Gnar)" as a virtual function in animal, and then implement the corresponding Gnar member functions in cat and dog respectively. As shown in the preceding figure, animal: Gnar calls have different effects, as shown below:
Cat cat1, cat2; dog; animal * pa [] ={& cat1, & dog, & cat2 };
For (unsigned long I = 0; I <sizeof (PA); I ++) Pa [I]-> Gnar ();
The above container PA records the reference of a series of animal instances (for reference, refer to "C ++ from scratch (8)"). Its semantics is that this is three animals, as a result, I don't know anything (as if this TV has 10 channels, and I don't know what it is ), each of the three animals is called once (called animal: Gnar), and the results are followed by the call of a cat, a dog, and a cat. This is what we have said before, increasing flexibility, also known as polymorphism, refers to the same animal: Gnar call, but shows different forms. The above for loop does not need to be written any more. It is "A means". To change its performance, you can use "another piece of code ", that is, different Derived classes are generated, and the instance reference of the derived classes is placed in the array Pa.
Therefore, a member function of a class is declared as a virtual function, indicating that the corresponding function of the resource mapped by this class should be a usage method, rather than an implementation method. The above "call" indicates that an animal "call" does not have to provide parameters or return values. You can call it directly. Therefore, consider the previous radio and digital radio. If one of the functions is the redeployment function, the corresponding function should be declared as a virtual function to indicate that the frequency increase or decrease will be given for the redeployment, the digital adjustment platform and the ordinary adjustment method are obviously different, but no matter. That is to say, people who use the radio don't care how the station is adjusted, but how the station is redeployed. Therefore, virtual functions indicate that the definition of a function is not important. The declaration of a function is important. A virtual function only has an existing meaning in a derived class. The definition of a virtual function provided by the parent class is redundant. Therefore, C ++ provides a special syntax to allow non-Definition of virtual functions. The format is very simple. Add "= 0" after the declaration statement of the virtual function, it is called a pure virtual function. As follows:
Class food; class animal {public: Virtual void Gnar () = 0, eat (Food &) = 0 ;};
Class Cat: Public animal {public: void Gnar (), eat (Food &);};
Class dog: Public animal {void Gnar (), eat (Food &);};
Void Cat: Gnar () {} void Cat: Eat (Food &) {} void dog: Gnar () {} void dog: Eat (Food &){}
Void main () {CAT; dog; animal ani ;}
When animal: Gnar is declared above, "= 0" is written after the statement to indicate that the elements mapped to it are not defined. What is the difference between this and "= 0? You can declare animal: Gnar directly without defining it. Note that the above animal ani; will report an error, because in animal: animal, the virtual function table of animal needs to be filled, and it needs the address of animal: Gnar. If it is a common declaration, no error will be reported here, because the compiler will think that the definition of animal: Gnar is in another file, and the connector will process it later. However, because "= 0" is used here to inform the compiler that it is not defined, the above Code will fail during compilation, and the compiler has determined that there is no definition of animal: Gnar.
But what if the animal: Gnar definition is added above? Animal ani; still reports an error because the compiler has determined that there is no definition of animal: Gnar, and the generation of the animal instance is denied even if the function table is not viewed. Therefore, the animal :: the definition of Gnar is useless. However, the ing element animal: Gnar now has a number in the address bar, so there is no problem when cat. Animal: Gnar. If the definition of animal: Gnar is not given, Cat. Animal: Gnar (); is still normal, but an error is returned during connection.
Note that the above dog: Gnar is private, while the animal: Gnar is public, and the result is dog. gnar (); will report an error while dog. animal: Gnar (); but there is no error (because it is a virtual function result or call dog: Gnar), that is, the so-called public is irrelevant to the type, it's just a syntax. There is also class food; you don't have to worry about whether it is declaration or definition. You just need to check what information it provides. There is only one -- there is a type name named "food", yesClassType. When declaring animal: Eat, the compiler only needs to know that food is a type name, rather than accidentally typing the wrong word, because food is not used here.
The above animal is called a pure virtual base class. The base class is the top class in the class inheritance system; the virtual base class is the base class with pure virtual member functions; the pure virtual base class is a non-pure virtual member function without member variables, only the base class of pure virtual member functions. The above animal defines a rule, also known as a protocol or an interface. That is, animals can be Gnar and eat, and an instance of food must be provided to indicate that animals can eat food. That is to say, the animal type is a manual, indicating the functionality of an animal, and its instance becomes meaningless, and it cannot generate an instance due to the use of pure virtual functions.
What if the above GNER and eat are not pure virtual functions? Then they must all be defined, and then animals are no longer an abstract concept, but there can be instances, then there can be such an animal, it is an animal, but it is not a specific animal (neither a cat nor a dog ). Obviously, such semantics is far from the pure virtual base class.
What about virtual inheritance? The member of the class that is inherited by virtual objects will be indirectly operated. This is its "A means", that is, to operate the member of the class that is inherited by virtual objects, different memory operations may be performed due to different offset values. However, the modification to the virtual table is only limited to modifying it to indirectly operate the same instance if it appears repeatedly, therefore, the root cause of virtual inheritance is to solve the two hunger problems of whales mentioned in the previous article, and its significance is just the implementation of an algorithm. This leads to the inability to determine whether to inherit the parent class from virtual machines when designing marine creatures and breast animals. It depends on whether the derived classes are similar to whales, this is not a good phenomenon.
Static)
As mentioned in "C ++ from scratch (v)", static means that every operation has not changed, while dynamic means that every operation may change. C ++ provides the static keyword, which is the same as the public and virtual keywords above. It is just a syntax identifier, not a type modifier. It can act before a member to indicate that the member remains unchanged for each instance, as shown below:
Struct a {static long a; long B; static void ABC () ;}; long A:;
Void A: ABC () {A = 10; B = 0 ;}; void main () {A; A. A = 10; A. B = 32 ;}
The above a: A is the static member variable of structure a, and a: ABC is the static member function of. What are the changes? The type of the above ing Element A: A will not be long A: But long. Similarly, the: ABC type is changed to void () instead of void (::)().
First, the members must be static for their class instances, that is, the member variables are the same for the memory address identified by each instance, the memory address modified by the member function for each this parameter remains unchanged. The above changes a: A and A: ABC to the normal type, instead of the Offset type, they eliminate their dependencies on the instance, and then implement the above static.
Because the instance dependency is eliminated above, that is, the member function removes this parameter, the member variable maps an exact memory address instead of an offset, so struct a {static long ;}; the variable A: A is declared. Its name is a: A and its type is long. The ing address is not given, that is, it is not defined yet, therefore, it must be defined again in the global space (that is, not in any function body), followed by long A: ;. Similarly, the: ABC type is void (), and The this parameter is removed, and then B = 10 in a: ABC is equivalent to a: B = 10 ;, it is found that A: B is an offset type. If this parameter is required, it is equivalent to this-> A: B = 10 ;. Result A: ABC does not have the this parameter, which is incorrect. For a = 10;, it is equivalent to a: A = 10;, but this variable already exists, so there is no problem.
Note that the above a. A = 10; is equivalent to a. A: A = 10; and A: A is not of the Offset type. Shouldn't an error be reported here? C ++ specifically allows this type of mismatch, where "A." is equal to none, because this is the static member we want to present. That is, a A, B;. A = 10; B. A = 20; after execution,. A is 20, because no matter which instance, the operation on member A: A changes the memory identified by the same address.
What does it mean? The difference between them and common variables is that their names are limited by a:, and thus they are dedicated to Class. For example, the height and width of the house door are fixed. Two houses are built by a company, and their doors have the same height and width, therefore, the door height and width should be used as static Members of the House made by the company to record the actual height and width, but they do not need to change because of the instance.
In addition to members, C ++ also provides static local variables. A local variable is a variable in the function body, which is enclosed by a pair of "{}" and has a limited scope. For a function, each time a function is called, because the local variables in the function are allocated to the stack, as mentioned previously, these variables are actually relative values, and each time the function is called, the actual corresponding address may be different due to stack reasons. As follows:
Void ABC () {long a = 0; A ++;} void BCD () {long d = 0; ABC ();}
Void main () {ABC (); BCD ();}
The address of local variable a generated when ABC is called in the preceding main is different from the address of a generated when ABC is called in BCD, the principles are described in C ++ from (15th. Therefore, the static local variable indicates that the address of the variable does not change no matter how it is called. As follows:
Void ABC () {static long a = 0; A ++;} void BCD () {long d = 0; D ++; ABC ();}
Void main () {ABC (); BCD ();}
The address of the above variable A is a fixed value, instead of the original relative value. In this way, the address of variable A obtained by calling ABC in main is the same as that obtained by calling ABC in BCD. The above is equivalent to the following:
Long g_abc_a = 0; void ABC () {g_abc_a ++;} void BCD () {long d = 0; D ++; ABC ();}
Void main () {ABC (); BCD ();}
Therefore, the initialization of static local variable A in the above ABC has actually been done before the main is executed, instead of imagining the initialization only when ABC is called for the first time. After the above code is executed, the value of a in ABC is 2 because of the two calls of ABC.
What does it mean? This variable is used only in this function, and its life cycle needs to exceed the execution period of the function. It does not provide any semantics (because the provided "used in this function" can be done using local variables), but when some algorithms need to use global variables, at this time, this algorithm is mapped into a function, so static variables have a good naming effect-both the survival of global variables and the semantics of local variables.
Inline)
Function calling is less efficient. Before calling a function, you need to store the parameters according to the calling rules, and then pass the parameter memory, we also need to record the call address to ensure that the function can return to the call place after execution (The details are discussed in C ++ from (15th ), however, it can reduce the length of the Code, especially when the function body is large and the Code calls it more often, it can greatly reduce the length of the Code (as if the loop is 10 times, if you do not write a loop statement, you need to copy the code in the loop body 10 times ). However, it is possible that the number of calls is small and the function body is small. At this time, the reason why the function is mapped is to make the semantics clearer. In this case, the execution efficiency rather than the code length may be more important. Therefore, C ++ provides the inline keyword.
When defining a function, you can write inline before the Definition Statement, indicating that when calling this function, the code for storing and passing parameters is not written in the call area as before, expand the function body in the call, as if we had copied the code in the loop body 10 times. In this way, the code execution efficiency will be improved without passing parameters, but the length of the final generated code may become longer due to excessive expansion. As follows:
Void ABCD (); void main () {ABCD () ;}inline void ABCD () {long a = 0; A ++ ;}
The above ABCD is the inline function. Note that the declaration of ABCD does not write inline, because inline is not a type modifier. It only tells the compiler to record more information when generating this function, the connector then expands it according to the information before the connection. Note: "Depending on the situation", that is, the compiler may be smart enough to find that there are too many calls to the corresponding function during the connection, and it is not suitable for expanding and not expanding. In this regard, different compilers provide different processing methods. For VC, it provides a keyword _ forceinline to indicate that the corresponding function must be expanded, regardless of the situation where it is called.
As mentioned above, for function definitions written in type delimiters, the compiler regards them as inline functions. After the inline function is changed, you no longer need to know which definition should be used to generate the address because multiple intermediate files have provided the function definition, because the address of the function is no longer required for all calls to these functions, the function will be expanded directly there.
Const (constant)
As mentioned above, the height and width of the door of a company's house should be static member variables, but it is obvious that during the whole period of the House's instance existence, the door height and width remain unchanged. C ++ specifically proposes a type modifier-Const. The type it modifies indicates that the number of the address type modified by that type cannot be used for write operations. That is, if it is a const type, it can only be read and cannot be modified. For example, const long a = 10, B = 20; A ++; A = 4; (Note that cosnt long a; is not supported, because subsequent Code cannot modify, if the value of a cannot be changed, then A has no meaning ). Here, both a ++; and A = 4; will return an error because the type of A is cosnt long, indicating that the memory value corresponding to the address of a cannot be changed, and both a ++ and A = 4; want to change this value.
Since const long is a type, it is normal to have const long *, which indicates the pointer whose type is const long. Therefore, according to the type match, there are: const long * P = & B; P = & A; * P = 10 ;. Here, P = & A; matching by type is normal, while P is a pointer of the long type of the constant, there is no problem. However, * P = 10; an error is returned because * P converts the number of P directly to the address type, which is the long type of the constant. Therefore, an error occurs when writing data to it.
Note: const long * const P = & A; * P = 10; In the left-to-right order, the above p type is const long * const, which is a constant of the Long TYPE pointer of the constant, indicating that the memory value corresponding to the P address cannot be modified, therefore, P = & A; in the back will be incorrect, which violates the meaning of Const. * P = 10; is also incorrect. However, you can:
Long A = 3, * const P = & A; * P = 10;
The above p type is long * const, which is a constant of the long type, so it must be initialized. Subsequent P = & A; errors will be reported because P is long * const, but * P = 10; there is no problem, because there is no problem after converting long * into long. So there are:
Const long a = 0; const long * const P = & A; const long * const * PP = & P;
As long as the modifier order is from left to right, and all const modifiers are converted to the type on the left of the pointer type modifier "*" in the corresponding type due to the conversion of the content operator, therefore, * PP is const long * const, and * P is const long.
Note that C ++ allows the following usage:
Struct a {long a, B; void ABC () const ;};
Void A: ABC () const {A = 10; B = 10 ;}
The above a: ABC type is void (A:) () const, which is equivalent:
Void a_abc (const A * This) {This-> A = 10; this-> B = 10 ;}
Therefore, the above a = 10; and B = 10; will return an error because the type of this is const *. The above indicates that the value of the member variable cannot be modified in function A: ABC, because the parameters of this change to const a *, but the value of the static member variable of the class can be modified, for example:
Struct a {static long C; long a, B; void ABC () const;} Long A: C;
Void A: ABC () const {a = B = 10; C = 20 ;}
Equivalent to: void a_abc (const A * This) {This-> A = This-> B = 10; A: c = 20 ;}. Therefore, the value of a: C can still be modified.
What is the significance? For details about const semantics, refer to another article I wrote, "semantic needs".
Friend)
The sender has the function of sending waves, and the receiver has the function of receiving waves. The sender, receiver, and radio waves are three types, first, the sender must be able to modify some member variables of the radio wave because the information is transmitted to the electric wave. However, these members of the radio wave should be protected, otherwise, any stone can receive or modify the information carried by the electric waves. Similarly, the recipient needs to be able to access some members of the radio waves modified with protected to receive the waves, which is troublesome. If two common member functions are defined in the radio wave, so that the sender and receiver can use them to access the protected members, that's all? This is exactly what many people have done. Since the sender can use the public member function to modify members of the radio waves, can the stone use the member function to modify the electric waves? So there was no door, but a door was locked. To eliminate this problem, C ++ proposed the concept of friends.
When defining a custom type, declare a custom type or function in the Type Definition operator "{}", and add the keyword "friend" before the declaration or definition statement, for example:
Class aggreger; Class sender;
Class wave {private: Long B, C; friend class extends er; friend class sender ;};
The above two member classes of the wave are declared to indicate that the receiver and sender are qualified for the wave, that is, the following:
Class A {PRIVATE: long a;}; Class wave: Public {... };
Void receiver: ABC () {wave WAV; WAV. A = 10; WAV. B = 10; WAV. A: A = 10 ;}
Since the attacker is a member of the wave class, you can directly access the wave: A, wave: B, but WAV. a: A = 10; an error will be reported, because a: A is a private member of A, and wave does not have the permission to ask questions about it, and the permission of the attacker is equivalent to that of wave, therefore, the permission is insufficient.
Similarly, you can also have a friend function, that is, to give a declaration or definition of the function. Add friend before the statement, as shown below:
Class extends er {public: void ABC ();};
Class A {PRIVATE: long a; friend void receiver: ABC ();};
In this way, the handler Er: ABC is used as the member function of A, and in the handler Er: ABC, it has all the permissions of Class.
Pay attention to the following information:
Class A {PRIVATE: long a; friend void receiver: ABC () {long a = 0 ;}};
The receiver: ABC function is defined here. Because it is defined in the Type Definition operator, as mentioned earlier, the receiver: ABC function will be modified as the inline function.
So what is the significance of the member function? If an operation needs to operate the protected members of two resources at the same time, the operation should be mapped to the member function. If stamp requires two resources: file and chapter, the function mapped to stamp should be the member function of the file and chapter.
Namespace
The static member variable is described earlier. Its semantics is dedicated to a class and is independent from the class instance. The key difference between the static member variable and the global variable is that the name has a qualifier (I .e., ": a: A is a static member variable of A, then the name A: A can show that a belongs to. Therefore, to express this subordination, You need to define the variable as a static member variable.
Consider a situation where ing mining. But what should I do if mining on land is obviously different from mining on the seabed? Map two functions named miningonland and miningonseabed respectively. Well, what should I do if I need to map it to land exploration and seabed exploration? Maps to prospectonland and prospectonseabed. What should I do if I need to map to land drilling and submarine drilling? Obviously, it seems far-fetched to express semantics by name, but it is even more unreasonable to use static member functions. Therefore, C ++ provides a namespace, the format is namespace <name >{< declaration or definition statements> }. <Name> is the name of the defined namespace, and <declaration or Definition Statement> is multiple declaration or definition statements. As follows:
Namespace onland {void mining (); void prospect (); void artesianwell (){}}
Namespace onseabed {void mining (); void prospect (); void artesianwell (){}}
Void onland: mining () {long a = 0; A ++;} void onland: Prospect () {long a = 0; A ++ ;}
Void onseabed: mining () {long a = 0; A ++;} void onseabed: Prospect () {long a = 0; A ++ ;}
The preceding six elements are defined, and each type is void (). Note that the definitions of onland: artesianwell and onseabed: artesianwell are directly written in "{}", which will be the inline function. In this way, the names of the six variables defined with delimiters can reflect the subordination from the name, and the semantics is better than the original one. onseabed: Prospect indicates the exploration in the seabed. Note:
Namespace A {long B = 0; long a = 0; namespace B {long B = 0; float a = 0.0f }}
Namespace c {struct ABC {long a, B, c, d; void ABCD () {a = B = c = d = 12 ;}} AB ;}
Namespace d {void ABC (); void ABC () {long a = 0; A ++;} extern float BD ;}
That is, any declaration or definition statement can be put in the namespace, or the custom structure can be modified. Therefore, C: abc a; A. ABCD (); can be used ();. Note that C ++ also allows namespace aliases, such as: namespace AB = C; AB: ABC A; A. ABCD ();. Here we create a new name AB for namespace C, just like the typedef mentioned previously.
Note that the effect of custom type definition is similar to that of namespace, for example, struct a {long a ;}; A:, like a namespace, a qualifier is added to the name of the ing element. However, we should know that structure A is not a namespace, that is, namespace abc = A; and it will fail. The namespace is like the custom structure of all static members.
To facilitate namespace usage, C ++ provides the Using Keyword, followed by the namespace and namespace names, which copies all the ing elements in the corresponding namespace, however, all the delimiters before the name are removed, and the valid regions of these elements are in the location of using, such:
Void main () {using namespace C; abc a; A. ABCD ();} abc B; B. ABCD ();}
The above abc B; will fail, because the valid region of using namespace C; is only in the previous "{}", and the output is invalid. Therefore, C: abc B; b. ABCD ();. What is the purpose? Easy to write. Because onland: prospect must be written every time you call onland:, it seems a little cumbersome. If you know that onseabed members are not used in a region, you can use the using namespace onland; to reduce the complexity of the Code.
Note that C ++ also provides a better using method, that is, you only want to remove the qualifier of A ing element in the namespace, for example, removing only onland :: prospect while other maintenance functions can: Using onland: prospect; prospect (); mining ();. Here mining (); will fail, while prospect (); will succeed, because using onland: prospect; only removes the onland: Prospect qualifier.
At this point, most of the content of C ++ has been basically described, but the template and exceptions are not described (there are also custom Operator overloading, out of space, in C ++ from (17th), they contain very few semantics, which is largely the same as the switch statement, it's just an algorithm package. Next, I will introduce the object-oriented programming ideology, and introduce the concept of "world" to illustrate how to design the inheritance system of classes and classes based on semantics.