[Object-Oriented Programming]
I have written the article for the first time, and it is more than one hundred. I just hope that some of the understanding of some understanding of object-oriented programming can have some small sites on people with common hobbies, and they will not help.
[Text involves the title description] 1. Variable: This title includes two parts. Built-in type instance (such as int, float, char, etc.) user-defined type instance (such as class, union), structure, etc.)
At the same time, this article sometimes has a general variable and function as a program member. 2. Parent class / subclass: Inherited as the parent class relative to the inheritance level; inherited as subclasses. 3. Object: This article Instance of a class (AN Instance of a class)
************************* Basic part ************** ************* [Memory Object Model Summary] Because this article is mainly to discuss the performance of the polymorphism in the language level, I don't plan to do too deeply discussions, just for this article. Interpretation, do some targeted instructions, conceptual explanation of memory object model.
A member function of the C class type, we can see them as a function in the C language. It is just a certain related process by the compiler to prevent naming conflicts. At the same time, in addition to the static member functions in the class, these functions add a parameter (THIS pointer) than the ordinary C language function because the member variables in the object can be handled. So we didn't see anything related to member functions in the Class's object memory layout.
Of course, if you have a Virtual function in the class declaration or in the inheritance hierarchy, you will see the existence of a "virtual function pointer" in the memory layout. When we don't use a single inheritance, the situation has become more complicated. As mentioned earlier, this article mainly explains how to use language on language usage, so I will not talk about more about memory layout. You need to understand the peers, please refer to books for object-oriented programming.
[Program Member Lifecycle Summary] Storage space: Define the storage form of program members in the program (or translation unit). As we often encounter, there are many programs global variables, program local variables, etc. Concept. Decide the life cycle of the variable. This concept mainly points out which memory part of the variable is placed in the program, such as program data segment, program stack, etc. Lifecycle: The program member is available in that time, simple talk It is a time a member of the program run, and we will call this time as this member of this member. Visibility: Which interfaces (class, functions) can reference program members link mode: Concept is one The declaration unit declares whether the member can be used by other translation units that can be programmed.
********************************************************************************************* ************* [Important three conclusions] For the explanation of the introduction class: class cbase {public: basefunc () {}}; class cderived: public cbease {public: derifunc () {}};
☆ Conclusion One ☆. If we point to a [subclass object] Point by [Parental Class Pointer], then we can only call the function defined in the parent class type (specified definition) through Pointer. We write: CBASE * PBASE; Although we can point to the CDeriveD object with a pointer PBASE, because PBase is a CBase type pointer, we can only call (or reference) BaseFunc () and cannot derifunc ().
☆ Conclusion Two ☆ If we point to a [parent class "in one [subclass pointer], before we reference the function, we must use the RTTI to determine the specific type of the pointer to the object. This means to do explicit modeling conversion. This approach should be the practice of our proceeds.
CDERIVED * PDERI; CDERIVED * PDERI; CBASE ABASE ("jason"); Pderi = & abase; ☆ Conclusion Three ☆. If the parent class and subclasses define [member functions of the same name], we call a reference member through pointer calls this time The resolution of the function must determine which function we reference is based on the pointer type (note that the pointer actually pointing objects) is determined. In fact, this conclusion is the function shield (MASK) function, this conclusion is very important, because here is Not a virtual function, all management, so this conclusion is very killing, and then I will explain this conclusion.
*********************************** Interpretation section ************ *************
☆ Conclusion explanation ☆:
Why is this, let's take a look at an example to understand why language designers use such a strategy?
#include
Class classa {public: int m_data1; void func1 () {} Virtual void vfunc1 () {} Virtual void vfunc2 ()}}};
Class classb: public classa {public: int m_data2; void func2 () {} Virtual void vfunc1 ()}}
When we write such a function; see if this function is implemented?
Void change (Classa & Ca) {ca.func1 (); ca.func2 (); //ca.func3 (); ca.vfunc1 (); ca.vfunc2 ();} When we call functions: Classa Ca; Classb CB; / * Call instructions, when we call this, everyone should understand that the FUNC3 () function cannot be called because this function does not exist at Classa. It's very simple, but the complex problem itself is very simple. We continue the following example * / change (ca); / * You may say that you should call the FUNC3 () function, good Classb does exist a name Call func3 () function, but we still can't call him through the function above, why? Please look at the explanation of me * / change (cb);
/ * Because we are referenced by a parent class to reference a subclass of type. From the implementation details of the function, our purpose is clear, that is to achieve polymorphism, because we can know that the function parameter reference to the true type of the object is used, maybe Classa may also be Classb, of course we will The function of calling the func3 () cannot be raised. We will implement the function as the function will be blocked when the compiler.
☆ Conclusion Two ☆ This conclusion is a problem with programmer programming, because the language provides flexibility, but how to use the programmer itself, if you don't understand the language itself, you write the code is often a problem This can only blame us, to study, it is absolutely not to say that this language is not good.
****************************************************************************************************** * Many languages tell what is simple and concise, I am talking about a very vivid example, after reading this example, I don't know what changes have you changed for those who are so-called concise languages. Ha ha ~~~~
Frequently, the same person will talk about a certain business company is too free, seriously affecting what you have created. Have you thought about these words? Let me understand, if this peer is replaced by a relatively free company, according to the reason, his creativity should be able to get a certain procedure release (it is played). This is the benefits of freedom from small to the big. At the same time, because of our peers, he thinks to strictly demand its own, so he can grasp your direction even in space in freedom.
Ok, it's almost over time. Now returning to the topic, a language that gives the programmer's degree of freedom, we call a relatively high language. In such a language environment, we can not use this flexibility, sometimes cause a mistake, but we should not blame the language itself. There is only one thing we need to do, it is to try to improve your own. Level.
The language of the freedom is very low, we have lost this flexibility, and we are still unlikely when we want to expand freedom. But in order to get free to poison in the environment in the freedom of freedom, we will strictly ask yourself.
I am built in the programmer is the programmer itself, and the programmer is not the basis of the programming machine. Regardless of how software production is not (at least in the year), it is like the traditional production industry, let alone have now entered the "Man Management" (Knowledge Management) era. *********************************************************** *********
☆ Conclusion Three ☆ Speaking of this conclusion, actually is Mask issued with Override, OverLoad in C . With the above analysis, we also understand this problem in a breath. I am using the << Effective C >>, and herein. But here also join some of my instructions, so I think it is easy to understand.
Let's take a look at the example that may make you crazy.
Class base {public: void f (const base "{} virtual void f (int x)}}}
Class Derived: Public Base {public: Virtual Void F (Double * Pd);
Derived * pd = new derived; pd-> f (10); // error!
There is a function shielding effect, if you are unclear, please look at the conclusions above again.
This is not very reasonable, but ARM provides this behavior to understand. Assume that when you call f, you really want to call the version in Derived, but accidentally use the wrong parameter type. Further hypothesis is the lower layer of the inherited hierarchy, you don't know that Derive has indirectly inherits a base class baseclass, and BaseClass declares a virtual function f with an int parameter. In this case, you will invoke Baseclass :: F, one you don't even know the function it exists! In the case of using a large class hierarchy, this error occurs often; so, in order to prevent it, Stroustrup decides to enable the derived class to hide the base class member according to the name.
By the way, if you want Derived users to access Base :: F, you can easily accomplish it through a using declaration:
Class Derived: public base {public: using base :: f; // introduced Base :: F into // derived spatial range Virtual Void F (double * pd);}; derived * pd = new derived; pd-> f (10); / / correct, call Base :: F
Another selection is an inline function:
Class Derived: Public Base {public: Virtual Void f (int x) {base :: f (x);} Virtual void f (double * pd);
Derived * pd = new derived; pd-> f (10); // correct, call derived :: f (int), // Indirect call Base :: f (int)