How is a virtual method called? (single inheritance vs. multiple inheritance)

Source: Internet
Author: User

We know that a pointer to a parent class can call the virtual method of the subclass, because the subclass method will overwrite the same method of the parent class, through which we can find the address of the object instance, you can find the pointer to the corresponding method table through the instance address, and through the method name, you can determine the position of this method in the method table, just call it directly, during Multi-inheritance, a class may have multiple method tables, and multiple pointers to these method tables. A class has multiple parent classes, how can I use a pointer to a parent class to call a virtual method?

In fact, the previous few words are not really clear. In single inheritance, how does the parent class call the virtual method of the subclass, and how does the inheritance implement this, please read it carefully.

Let's first look at how single inheritance is implemented. First, let's look at two simple classes:

#include <iostream>   ~ <<<< SetA(= B: ~ <<<< <<<< (*Fun)(<<<<** pVtab0 = (**)& ( i=; (Fun)pVtab0[][i]!=NULL; i++= (Fun)pVtab0[<< <<i<<<<* b1=&<<<<** pVtab1 = (**)& ( i=; (Fun)pVtab1[][i]!=NULL; i++= (Fun)pVtab1[<< <<i<<<<<<<<** pVtab2 = (**)&* ( i=; (Fun)pVtab2[][i]!=NULL; i++= (Fun)pVtab2[<< <<i<<<<<<<<&b<<<<<<b1<<endl<<

The running result is as follows:

Through the running result, we know that the sub-class virtual method is called through the pointer pointing to the sub-class of the parent class. In a single inheritance, although the parent class has a virtual method table of the parent class and the Child class has a virtual method table of the Child class, the Child class does not point to the pointer of the parent class virtual method, in a subclass instance, The subclass and the parent class share a virtual method table. Of course, there is only one pointer to the method table. Why can we share a virtual method table, the first method of the virtual method table is the destructor. The subclass method overwrites the same method of the parent class. The new virtual method of the subclass is placed behind the virtual method table, that is to say, the virtual method table of the subclass completely overwrites the virtual method table of the parent class, that is, each virtual method of the subclass corresponds to the virtual method of the parent class, and the indexes in various method tables are the same.

However, this is not the case in Multi-inheritance. The first inherited class is identical in documentary inheritance, but not in subsequent inherited classes, take a closer look.

Let's start with three simple classes.

#include <iostream>   ~ <<<< ~ <<<< <<<< C: A, ~  GetB()<<<< <<<< <<<< (*Fun)(* c=* a=* b=<<<<(C)<<endl<<<<<<c<<<<<<a<<<<<<b<<endl<<endl<<<<<<** pVtab1 = (**)&* ( i=; (Fun)pVtab1[][i]!=NULL; i++= (Fun)pVtab1[<< <<i<<<<&*pFun<<    <<endl<<<<<<= (**)&* ( i=; (Fun)pVtab1[][i]!=NULL; i++= (Fun)pVtab1[<< <<i<<<<&*pFun<<    

The running result is as follows:

Speaking from the results:

Sizeof (C) = 20. We are not surprised. During single inheritance, the parent class and subclass share a pointer to the virtual method table. In multi-inheritance, similarly, the first parent class and the subclass share this pointer, and the second parent class has its own independent pointer, in fact, the parent class instance maintains a complete structure in the sub-class memory, that is to say, in multi-inheritance, and so on, the instance is spliced by each parent class instance, of course, some secondary pointers may be added due to the complexity of inheritance.

Pointer a and pointer c point to the same address, that is, the first address of class c. The difference between the address referred to by B and the address referred to by a is 8 bytes, that is, the size of the Class A instance, that is to say, in the memory layout of C, the instance of A is first stored, and in the instance of B, sizeof (B) = 8 (the int B Field and the pointer to the B virtual method table). At home, the int C Field of c is exactly 20 bytes.

Unexpectedly, Method B: SB, C: GetB does not appear in the method table of class C, and C :: the GetB method in B is overwritten by C. Why is it not displayed in the C method table? As mentioned in the book "exploring the C ++ Object Model in depth", these two methods should appear in the C method table at the same time, and will also overwrite the virtual method table of B. It may be that different compilers have different implementations. I use VS2010. In this book, the compiler cfront is used.

Okay, we don't have to worry about the differences in implementation of different compilers. This is a small difference, and the calling mechanism of virtual methods is the same.

Let's analyze several small examples to see the implementation mechanism of the virtual method.

C * c = new C ();

A * a = c;

A-> GetA ();

C-> GetA ();

C-> GetC ();

As mentioned above, a and c point to the same address and share the same virtual method table. The address of the GetA and GetC methods is in this method table, it is much simpler to call, which is roughly like the following:

A-> GetA ()-> (a-> vptr1 [1]) (a); // The index of GetA in the method table is 1

C-> GetA ()-> (c-> vptr1 [1]) (c); // The index of GetA in the method table is 1

C-> GetC ()-> (a-> vptr1 [2]) (c); // The index of GetC in the method table is 2

Vptr1 indicates a pointer to the first method table of class C. The actual name of this pointer is more complex. For now, the pointer to the first method table of class C is named vptr2, this pointer will be used below.

Analyze several lines of code:

B * B = c;

C-> GetB ();

B-> GetB ();

If pointer B and pointer c point to different addresses, then B * B = c; what exactly has it done? It is roughly converted to the following:

B * B = c + sizeof ();

The size of A added to the address referred to by c is exactly the address referred to by B.

C-> GetB (); conversion is also required, because the GetB method is not in the method table referred to by c at all, and may be converted to this way (I do not know what the conversion actually looks like)):

This = c + sizeof ();

(This-> vptr2 [2]) (c );

If the GetB method is in the method table referred to by vptr1 as the cfront compiler said, no adjustment to this pointer is required. If the GetB method is in the method table referred to by vptr1, the method table becomes larger and is repeated with other method tables.

B-> GetB (); you do not need to perform too many conversions, because B points to vptr2, which may be converted to the following:

B-> GetB ()-> (B-> vptr2 [2]) (B); // The index of GetB in the method table is 2

In short, the method table referred to by the pointer should be adjusted if there is no method to be called. The virtual method needs to be called through the method table. Compared with non-virtual methods, the performance will be a little slower, this is also one of the features that people often say that C ++ is inferior to C.

Virtual Multi-inheritance is more troublesome, and it may be pitted if you are not familiar with it. This book explores the C ++ Object Model in depth. Do not declare nonstatic data members in a virtual base class. If you do this, you will be closer and closer to the complex abyss, and you will not be able to pull it out.

Use virtual base class as an interface.

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.