In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-02 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article is mainly about "virtual functions in C++". Interested friends may wish to have a look at it. The method introduced in this paper is simple, fast and practical. Next, let the editor take you to learn the virtual functions in C++.
The assembly language is difficult to read, especially for some friends who do not have the basis of assembly. therefore, this paper translates the assembly into the corresponding C language to facilitate readers to analyze the problem.
1. Code
In order to express the problem conveniently, this paper selects two classes with only virtual functions and, of course, its constructors, as follows:
[cpp] view
Plaincopyprint?
Class Base
{
Public:
Virtual void f () {}
Virtual void g () {}
}
Class Derive: public Base
{
Public:
Virtual void f () {}
}
Int main ()
{
Derive d
Base * pb
Pb = & d
Pb- > f ()
Return 0
}
two。 Virtual function table of two classes (vtable)
The above C++ code can be generated into its corresponding assembly code using the test.cpp +-Wall-S command.
[cpp] view
Plaincopyprint?
_ ZTV4Base:
.long 0
.long _ ZTI4Base
.long _ ZN4Base1fEv
.long _ ZN4Base1gEv
.weak _ ZTS6Derive
.section .rodata. _ ZTS6Derive, "aG", @ progbits,_ZTS6Derive,comdat
.type _ ZTS6Derive, @ object
.size _ ZTS6Derive, 8
_ ZTV4Base is a data symbol, and its naming convention is based on the internal rules of Gmail +. If you want to see the symbol name that really represents C++, you can use the c++filt command to convert it, for example:
[lyt@t468 ~] $c++filt _ ZTV4Base
Vtable for Base
The _ ZTV4Base symbol (or variable) can be seen as an array, whose first item is 0, and the second item _ ZIT4Base is type information about Base, which is related to typeid. For the sake of discussion, we omit these two items of data. Therefore, the structure of the vtable of the Base class is translated into the corresponding C language definition as follows:
[cpp] view
Plaincopyprint?
Unsigned long Base_vtable [] = {
& Base::f ()
& Base::g ()
}
Derive is even more similar, only slightly different:
[cpp] view
Plaincopyprint?
_ ZTV6Derive:
.long 0
.long _ ZTI6Derive
.long _ ZN6Derive1fEv
.long _ ZN4Base1gEv
.weak _ ZTV4Base
.section .rodata. _ ZTV4Base, "aG", @ progbits,_ZTV4Base,comdat
.align 8
.type _ ZTV4Base, @ object
.size _ ZTV4Base, 16
The corresponding C language is defined as follows:
[cpp] view
Plaincopyprint?
Unsigned long Derive_vtable [] = {
& Derive::f ()
& Base::g ()
}
As you can see from the vtable of the above two classes, the first item in Derive's vtable overrides the first item of the Base class vtable. As long as the subclass overrides the virtual function of the base class, the corresponding item of the subclass vtable will change the vtable entry of the parent class. This process is handled automatically by the compiler, and the vtable content of each class is placed in the data segment.
3. Who tied the object to vtable?
The above code only defines the content of the vtable for each class, but we know that an object with a virtual function has a vtable pointer inside it, pointing to the vtable, so when was it specified? Just look at the assembly code of the constructor and you can see at a glance:
The compiled code for the Base::Base () function is as follows:
[cpp] view
Plaincopyprint?
_ ZN4BaseC1Ev:
.LFB6:
.cfi _ startproc
.cfi _ personality 0x0,__gxx_personality_v0
Pushl ebp
.cfi _ def_cfa_offset 8
Movl esp, ebp
.cfi _ offset 5,-8
.cfi _ def_cfa_register 5
Movl 8 (% ebp),% eax
Movl $_ ZTV4Base+8, (eax)
Popl ebp
Ret
.cfi _ endproc
The symbol ZN4BaseC1Ev is the internal symbolic name of the C++ function Base::Base (), which can be restored using c++flit. The class in C++ can define data members and function members. But when converted to the assembly level, what is really stored in each object is the data member, as well as the virtual function table.
In the Base class above, since there are no data members, it has only one vtable pointer. Therefore, the definition of the Base class can be written as the following corresponding C code:
[cpp] view
Plaincopyprint?
Struct Base {
Unsigned long * * vtable
}
The two most critical sentences in the constructor are:
Movl 8 (% ebp),% eax
Movl $_ ZTV4Base+8, (eax)
$_ ZTV4Base+8 is the starting position of the virtual function table of the Base class, so the corresponding C code for the constructor is as follows:
[cpp] view
Plaincopyprint?
Void Base::Base (struct Base * this)
{
This- > vtable = & Base_vtable
}
Similarly, the constructor of the Derive class is as follows:
[cpp] view
Plaincopyprint?
Struct Derive {
Unsigned long * * vtable
}
Void Derive::Derive (struct Derive * this)
{
This- > vtable = & Derive_vtable
}
4. The most critical step in implementing runtime polymorphism
The value of vtable set in the constructor is obviously the same in all objects of the same type and will never change. The following is the assembly code generated by the main function, which shows how C++ uses vtable to implement run-time polymorphism.
[cpp] view
Plaincopyprint?
.globl main
.type main, @ function
Main:
.LFB3:
.cfi _ startproc
.cfi _ personality 0x0,__gxx_personality_v0
Pushl ebp
.cfi _ def_cfa_offset 8
Movl esp, ebp
.cfi _ offset 5,-8
.cfi _ def_cfa_register 5
Andl $- 16,% esp
Subl $32,% esp
Leal 24 (% esp),% eax
Movl eax, (esp)
Call _ ZN6DeriveC1Ev
Leal 24 (% esp),% eax
Movl eax, 28 (esp)
Movl 28 (% esp),% eax
Movl (% eax),% eax
Movl (% eax),% edx
Movl 28 (% esp),% eax
Movl eax, (esp)
Call *% edx
Movl $0,% eax
Leave
Ret
.cfi _ endproc
Andl $- 16,% esp
Subl $32,% esp
These two sentences allocate space on the stack for the local variables d and bp, that is, the following statements:
Derive d
Base * pb
Leal 24 (% esp),% eax
Movl eax, (esp)
Call _ ZN6DeriveC1Ev
Esp+24 is the first address of the variable d, press it on the stack first, and then call the constructor of d, which is translated into C language as follows:
Derive::Dervice & d
Leal 24 (% esp),% eax
Movl eax, 28 (esp)
This is actually assigning the value of & d to pb, that is:
Pb = & d
The most critical code is the following paragraph:
[cpp] view
Plaincopyprint?
Movl 28 (% esp),% eax
Movl (% eax),% eax
Movl (% eax),% edx
Movl 28 (% esp),% eax
Movl eax, (esp)
Call *% edx
The sentence translated into C language is also vivid:
Pb- > vtable [0] (bp)
The compiler will remember that the f virtual function is placed in item 0 of vtable, which is the compile-time information.
5. Summary
A lot of details about compilers and C++ are omitted here because of the need for ease of use. You can see the following information from the compiled code above:
1. Each class has its own vtable structure, and the compiler will fill in their virtual function table correctly.
two。 When the object is constructing the function, set the vtable value to the virtual function table of this class
3. Calling a virtual function during a pointer or reference is achieved by object- > vtable plus the offset of the virtual function.
Of course, this is just the implementation of Gmail +, which is slightly different from that of VC++, but the principle is the same.
At this point, I believe you have a deeper understanding of the "virtual function in C++". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 227
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.