Open from bottom layer and logic-in-depth analysis of objects such as C ++

Source: Internet
Author: User

What is a class and an object? These two questions are described in an abstract way in each c ++ book, giving us a almost perfect answer, then I seem to know what a class is and what an object is, but when I ask myself where the class is, where the object is, where the member method is, and where the member variable is, these definitions can only give one abstract answer.

In fact, the reason why we do not know the answer is that we have not figured out what the problem is. classes and objects are collections of member variables and member methods with access permissions, so we can follow the definition below. Of course, I cannot answer these questions, however, I am going to do three things in this article. Through these three things, I will be more familiar with objects and classes: 1. at the underlying implementation level, the object is saved in what form, and the object name is what the object's member variables are stored. 2. at the bottom layer, how does a member method exist? How does one distinguish it from global functions and how to overload it? 3. logically speaking, how to implement access permissions, Private, const, and static, and how to bypass the compiler to break through these permissions at the underlying level, for example, the object member variables are successfully accessed in the static method. For example, the member variables are successfully modified in the const method. For example, the private variables are successfully modified externally;

Then we will find that the so-called class mechanism of c ++ only sets a yoke on the neck of C and gives the key to it.

First problem: Memory representation of classes and objects. When I didn't learn C ++ before, many people say that C ++ is object-oriented and C is process-oriented, let me have the feeling that object orientation is object orientation. Then I asked what object orientation is. Then people will say that object orientation is an idea, (then I look up and look at the distance and think deeply, so that I have an impulse to beat him in the palm of my hand). This article does not explain what object-oriented means, because the process of understanding this idea is not achieved overnight, let's talk about what actually exists in the memory. After all, something actually exists. Classes are for the compiler, no memory exists, just like a struct, just like an array, and an object is something that exists. The object name is like a struct variable name, just like the array variable name (Some people say you are talking about it, the array name is the address, and what are your two items ),
The array name is an address. At the underlying implementation level, are the names not all addresses? The struct variable name and object name are also addresses. These three types are composite types, struct and object can be composite of different types, and arrays are composite of the same type, therefore, you can use array name plus 1 to find the address of the second element logically (but you must understand that this is all logical and is the benefit of the compiler ), however, the struct name plus 1 is not necessarily; Next we will look at how the memory is allocated in the next object creation process; the source code is as follows:

#include <iostream>using namespace std;class TextA {private:int a;int b;public:TextA();};TextA::TextA(){a=10;b=20;}int main(){TextA text;//cout<<sizeof(text);return 0;}

The code above is very simple. Define a text () and allocate memory for it. Let's take a look at the underlying implementation.

. Text: 00401_f _ main proc near; Code xref: Start + AFP. text: 004020.f. text: 00401_f _ text = byte PTR-8. text: 00401_f argc = dword ptr 8. text: 004020.f argv = dword ptr 0ch. text: 00401_f envp = dword ptr 10h. text: 004020.f. text: 0040366f push EBP. text: 004010a0 mov EBP, esp. text: 004010a2 sub ESP, 8
; None of the above;

. Text: 004010a5 Lea ECx, [EBP + _ text]. text: 004010a8 call _ texta. text: 004010ad XOR eax, eax. text: 004010af mov ESP, EBP. text: 004010b1 pop EBP. text: 004010b2 retn. text: 004010b2 _ main endp. text: 004010b2

This code is actually an important sentence of Lea ECx, [EBP + _ text], which roughly means to put the text address in ECx, and then

Call _ texta is the default constructor that calls texta (). Let's take a look at what this constructor has done to text;

. Text: 004020.e _ texta proc near; Code xref: _ main + 9p. text: 004020.e. text: 00401_e var_4 = dword ptr-4. text: 004020.e. text: 0040e e push EBP. text: 004020.f mov EBP, esp. text: 00401081 push ECx. text: 00401082 mov [EBP + var_4], ECx; this sentence means to put the address of the memory in ECx, that is, the address of the _ text mark, into the memory of the ebp-4 ;. text: 00401085 mov eax, [EBP + var_4]; then put it in eax ;. text: 00401088 mov dword ptr [eax], 0ah; 0ah is 10 in decimal format. Put 10 into the memory of the address stored in eax, that is, the first variable A of the text marked by _ text ;. text: 004020.e mov ECx, [EBP + var_4]; then, the address of the memory marked by text is put into ECx again ,. text: 00401091 mov dword ptr [ECx + 4], 14 h; then the address in ECx minus four, and the hex in the memory is 14h, which is 20, obviously, this memory is B ;. text: 00401098 mov eax, [EBP + var_4]. text: 00401_ B mov ESP, EBP. text: 00401_d pop EBP. text: 0040e e retn. text: 00401_e _ texta endp

Let's see whether text is the first address of its memory, that is, the address of the first element A. Therefore, at the bottom layer, the structure question, array and object are a kind of things; we didn't see the Member method above. Where is the member method? This is our second problem;

2. where is the member method: This involves a naming Crusher System. Of course, I do not understand the naming crushing principle, but it is like according to some features of your function during compilation, name the first section of a code segment in your function. Well, this sentence contains at least three levels of information. First, this mechanism is used during compilation, you can change the function name to the past or to the second. When the second function name applies this mechanism, the features are determined by the compiler. Different Languages vary. Third: the obtained name will be used to identify the first address of the code segment in the original function. The Code is also in the memory;
It is a bit abstract, so let's take a few examples: in C language, if the function name is the same, no matter the parameter type is the same, it cannot be compiled. This shows that this feature is the function name, so we can say that the function name in C language is the address of the function. In C ++, this is not the case if there is a heavy load, and there is a class member function, so this is not the case, function features in C ++ include the class name, function name, parameter type, and parameter quantity. Of course, there are some methods that do not belong to the class, that is, the global method; c ++ functions are placed in the code segment and use the function name (in fact, it is changed to identify the first address ); therefore, this explains several phenomena in the logic layer <1> an object passes through the logic layer.
Operators can only access methods of their own classes. <2> member methods are actually class-related and Object-independent (this sentence is not rigorous and may lead to some problems, we will discuss it in the third topic) <3> If a static type variable is defined in a member method and another object uses this method, this static variable is still in progress;

For example, the following code

#include <iostream>using namespace std;class TextA {public:void show(){static int a=1;cout<<++a<<endl;}};int main(){TextA ta;TextA tb;ta.show();tb.show();return 0;}

3 is output after 2, indicating that the two objects access the code of the same address. That is to say, these member Methods belong to the class rather than the object itself, which leads to several problems, for example, the static method is the class method. For example, what should I do when the member method modifies the object variable? What is the this pointer? Well, we will not leave these questions to the third topic, analyze and analyze the call process of a member method.

#include <iostream>using namespace std;class Text{private:int a;public:void set_a(){a=10;};};int main(){Text t;t.set_a();return 0;}

For ease of understanding, we write the code very easily. It's as simple as not even passing parameters, so simple as not having default constructor. (The Compiler won't add default constructor to you, although the teacher and many books say they will definitely add it, I don't believe it. I will explain the principle in the next blog.) Let's look at the underlying implementation of this code;

_main proc nearvar_4= byte ptr -4argc= dword ptr  8argv= dword ptr  0Chenvp= dword ptr  10hpush    ebpmov     ebp, esppush    ecxlea     ecx, [ebp+var_4]call    ??1facet@locale@std@@UAE@XZ ; std::locale::facet::~facet(void)xor     eax, eaxmov     esp, ebppop     ebpretn_main endp

We can call only one function at this bottom layer.

Call ?? 1facet @ locale @ STD @ UAE @ xz; STD: locale: facet ::~ Facet (void)
?? 1facet @ locale @ STD @ UAE @ xz is the result of name fragmentation. It identifies the first address of text: set_a (). How does it get the this pointer, view
Lea ECx, [EBP + var_4], this sentence means to put the address of the T mark in the register ECx, that is, the this pointer, in the function, we can use it to find a. After analyzing the static method, we will find that it does not have this sentence, so we cannot find this pointer;
#include<iostream>using namespace std;class TextA {private:int a;public:static void  show();}; void  TextA::show(){cout<<"dragonfive!";}int main(){TextA ta;TextA::show();return 0;}

Let's look at the underlying implementation

_main proc nearargc= dword ptr  8argv= dword ptr  0Chenvp= dword ptr  10hpush    ebpmov     ebp, esppush    ecxcall    sub_40107Exor     eax, eaxmov     esp, ebppop     ebpretn_main endp

Let's see, there is no lea sentence here, so we won't be able to get this pointer (this is the practice of the compiler. We can upload one by ourselves, in this way, we can break through the restrictions. This is part 3 of our content ;)

3. There are many rules in C ++, which seem strange. For example, Private Members cannot be accessed from the outside. Let's try it today:

#include<iostream>using namespace std;class TextA {private:int a;     public:    TextA(){a=10;}   void show_a();};void TextA::show_a(){cout<<a<<endl;;}int main(){TextA ta;ta.show_a();int *b=NULL;__asm{lea eax,ta;mov [b],eax;}*b=20;ta.show_a();return 0;}

Right, the first output is 10, because the initialization is 10, and then the second output is 20. Why? Because we get the address of, that is not to say that private is false. Naturally, it is not because private is the limitation of the C ++ compiler. We use assembler to steal the address of, compilation will naturally not go through the C ++ compiler and will not be subject to private restrictions, so we will know this private.
It's just about the compiler, and it has nothing to do with the storage of variables;
Of course, it can be inferred that some other restrictions are also like this. For example, we can allow the static method to access the attributes of the objects accessing it;

#include<iostream>using namespace std;class TextA {private:int a;public:TextA(){a=10;};static void  show();}; void  TextA::show(){int b;__asm{mov eax,[ecx]mov [b],eax}cout<<b;}int main(){TextA ta;__asm{lea ecx,ta;}TextA::show();return 0;}

lea ecx,ta;

It's because we manually transferred an address before calling it.

As you can see, there is no difference between C ++ and other languages in terms of underlying implementation. Pointers are still so powerful and dangerous;
The compiler only checks some restricted words to ensure part of the security. Why cannot it be absolutely safe, as I mentioned in the previous blog
The consistency of C ++ and the existence of pointers make everything within one degree; c ++ is used to allow the compiler to detect unsafe factors as much as possible through these restrictions,
Therefore, the C ++ function is a restricted language. The object is like the palace, and the Private member is like the harem part... the compiler opens the door, and only the pointer or address can be used to sneak into the harem for various friendly accesses...

Finally, I found that it seems to be a question, because it seems that the pointer is powerful (this may mislead beginners), and the restricted word is only a logical layer.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.