The principle of the virtual function of C + +

Source: Internet
Author: User

1. Look at the memory layout of a class if there is a virtual function:

Class a{       double i;       Int J;       virtual void foo () {}       virtual void Fun () {}};

Memory layout:

1>  class A       size (:1>        +---1>   0   | {vfptr}1>   8   | i1>  |  j1>        | <alignment member> (size=4) 1>        +---

As you can see, A has a vfptr, which is a pointer to a virtual table.

C + + creates a single virtualtable for each class that has a virtual function. The size is the number of virtual functions in this class +1/2 a slot (for runtime type identify). Each line in this virtual table is the address of the virtual function declared by this class.

Note: The position of the vfptr in the class is fixed, and is usually placed at the front. It affects the maximum byte-aligned bytes.

2. See if a class inherits from this class with a virtual function. It's memory layout:

Class Point{public:       virtual ~point () {};       Virtual float mult (float) =0;       Virtual float y () {return 0;}       Virtual float Z () {return 0;}       float _x;}; Class Point2d:point{public:       virtual ~point2d () {};       Virtual float mult (float) {return 0;}       Virtual float y () {return 1;}       float _y;}; Class point3d:point2d{       Virtual ~point3d () {};       Virtual float mult (float) {return 0;}       Virtual float Z () {return 0;}       float _z;};


Note that the vptr is placed at the end of the class, usually on the front (VS), and also in the final. It's good to know that.


You can see that the virtual table of point has 4 virtual functions.

POINT2D's virtualtable has 4 virtual functions, and the definition of POINT2D class finds that the Z () function in point is not modified, so the virtualtable of POINT2D also retains the Z () function address in point.

Each subclass has a table of virtual functions.

Note At this point: we can also define new virtual functions (functions that are not in the parent class) in the subclass, which adds a row to the virtual function table of the child class.

( Here is a special note: What is called the new virtual function, if the virtual function in the subclass is associated with a virtual in the parent class function has the same name and the function signature is identical, the virtual function address in the parent class is modified . Otherwise, if the function signature is not the same as the same name, a new row is added to the virtual table. )

<span style= "color: #333333;" >class a{public:virtual void foo () const{cout<< "A" <<endl;}}; Class B:public a{public:virtual Voidfoo () {cout<< "B" <<endl;}}; int _tmain (int argc, _tchar* argv[]) {       A *a=new B;       A->foo ();//a       return 0;} </span>

here b Span style= "color:red" >foo function signature with a foo function signatures are different, so b foo a b a does not have access to b foo scope permissions, So there is no ambiguity, that is, call a Foo

This is what we used to say about polymorphism. 3 elements: Inheritance, Virtual function, the same name function signature can be polymorphic.

More attention: Such a principle only applies to non-virtual inheritance, virtual inheritance, it is not such a principle.

Polymorphism is the essence:

Point * p=new point2d ();

P->y ();

At this point the address that P points to is an object of point2d, and it is obvious that its virtual table is point2d.

The call to the virtual function is invoked through VPTR. P-y (); C + + The actual code is (* p->vptr[3]) (p);

P->VPTR[3] is used to locate the Y function address, and P points to the address of POINT2D, which determines that the Y function of the call is the Y function in point2d. This enables polymorphism.

Note that while P points to the object address of point2d, the p at this point is scoped, and it cannot invoke something that does not belong to point, such as:p->_y;.

3. Virtual functions under Multiple inheritance

C Inherits A,c inheritance B,a and B have no relationship:

Class A{public:       char i;       Virtual Voidfoo () {cout<< "A" <<endl;}}; Class b{public:virtual void foo (int i) {cout<< "B" <<ENDL;}      virtual void Fun (int i) {cout<< "B" <<ENDL;}; Class C:public a,b{};

Because there is a vfptr in both A and B, there are two vfptr in C. and two vfptr in the interior are different names. For example: Vfptr_a and Vfptr_b

Memory layout:

1>  class C       size (:1>)        +---1>        | +---(base class A) 1>   0   | | {vfptr}-------------------------------a::foo1>   4   | | i1>        | | <alignment member> (size=3) 1 >        | +---1>        | +---(base class B) 1>   8   | | {vfptr}-------------------------------b::foo, b::fun1>        | +---1>        +---


At this point if: A *a=new C (); A->foo (); it's obviously called A::foo.

b* b=new C (); B->foo (2); it is obviously called B::foo. Note that at this point B is pointing to the start of B in C, not the start of C.

If Cc;c.foo ()/c.foo (2), it's all wrong. Because of the search mechanism of C + +. First in the C search, not found, and then go to the parent, but A and b are the parent class, and A and B have no relationship, so C + + to find, found two foo. Note that at this point the C + + search mechanism does not care about Foo parameters.

If Cc;c.fun (2); that's right. Because the compiler will traverse two vfptr and will only find one (*c.vfptr_b[2]) (&C), it will know that it should proceed as follows.

Summary: Under multiple inheritance, do not call functions with the same name in multiple parent classes. Note that this does not constitute an overloaded function even if the argument list is different. It is also obvious that, after all, these functions belong to different classes.

4. Virtual functions under Virtual inheritance

Do two experiments:

Class a{       public:virtual void foo () {cout<< "A" <<endl;}}; Class B:virtual public a{       public:virtual void foo () {cout<< "B" <<endl;}};

Memory layout:

1>  class B       size (8):1>        +---1>   0   | {vbptr}1>        +---1>        +---(virtual base A) 1>   4   | {vfptr}1>        +---


Class a{       public:virtual void foo () {cout<< "A" <<endl;}}; Class B:virtual public a{       public:virtual void foo (inti) {cout<< "B" <<endl;}};

Memory layout:

1>  class B       size (:1>)        +---1>   0   | {vfptr}1>   4   | {vbptr}1>        +---1>        +---(virtual base A) 1>   8   | {vfptr}1>        +---


Compared with virtual inheritance, if the virtual function in the subclass overrides the virtual function of the virtual base class, the subclass does not create a single vfptr.

If a virtual function in a subclass is not all a virtual function that overrides a virtual base class, and there are other virtual functions, the subclass creates a single vfptr.

Note the meaning of the override: the function name and the parameter are all the same, polymorphic.

It is also concluded that if the vfptr and vbptr belong to the same class, the vfptr is in front, because the position of vfptr must be fixed. And the position of the vbptr is not the same as fixed. But note: The memory distribution of the first experiment, because Vfptr and vbptr do not belong to the same class.

Note that these memory layouts are created under VS, and other compilers are unsure.

The principle of the virtual function of C + +

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.