The internal implementation method of polymorphism and virtual function in C + + _c language

Source: Internet
Author: User

1, what is polymorphism

Polymorphism can be simply summed up as "an interface, a variety of behaviors."

That is, the same message is sent to different objects, and different objects produce different behaviors (i.e. methods) when they are received. In other words, each object can respond to common messages in its own way. The so-called message, is called the function, different behavior refers to different implementations, that is, the implementation of different functions. This is a generic technique that uses the same code to implement different actions. This embodies the superiority of object-oriented programming.

Polymorphism is divided into two types:

(1) Compile-time polymorphism: mainly through the functions of the overload and template to achieve.

(2) Run-time polymorphism: Mainly through virtual function to achieve.

2. Several related concepts

(1) Overwrite, rewrite (override)

Override means that a member function of a base class is a virtual function, and a derived class defines a member function, except that the rest of the function body is the same as the member function of the base class. Note that if the function name is the same, the formal parameter or return type is different, it cannot be called override, but hide.

(2) overload (overload)

A function in which the same scope is born with multiple function names, but with different formal parameters. At compile time, the compiler selects the function that is finally called by the number and type of arguments.

(3) Hiding (hide)

Divided into two types:

1 local variables or functions hide global variables or functions
2 The derived class owns a member function or member variable with the same name as the base class.

The resulting result: the variables and functions of the global or base class are not visible.

3, a few simple examples

/************************************************************************************** 
* File:polymorphismtest * Introduction: Some characteristics of the test polymorphism. * Author:codercong * date:20141114 * lastmodifieddate:20160113 ***************************************************** /#include "stdafx.h" #include <iostream> using namespace std 
; 
  Class A {public:void foo () {printf ("1\n"); 
  virtual void Fun () {printf ("2\n"); 
} 
}; 
  Class b:public a {public:void foo ()//Because the Foo function of the base class is not a virtual function, it is hidden instead of overriding {printf ("3\n"); 
  } void Fun ()//rewrite {printf ("4\n"); 
} 
}; 
  int main (void) {a A; 
  b b; 
  A *p = &a; P->foo (); 
  Output 1. P->fun (); 
  Output 2. 
  p = &b; P->foo (); Output 1. Because P is a base class pointer, P->foo points to a function with a fixed offset. Which is the base class function P->fun (); Output 4. Polymorphism. Although P is a base-class pointer, it actually points to a subclass object. P->fun is pointing to a virtual function. 
According to the dynamic type, call the subclass function return 0; }

4, Run-time polymorphism and virtual function of the internal implementation

Read the above a few simple examples, I suddenly realized that this is polymorphic, so simple, understand!

Well, let's look at one more example:

Class A 
{public 
: 
  virtual void Funa () 
{ 
cout << "FunA1" << Endl; 
}; 
virtual void Funaa () 
{ 
cout << "FunA2" << Endl; 
} 
}; 
Class B 
{public 
: 
  virtual void Funb () 
{ 
cout << "Funb" << Endl; 
} 
}; 
Class C:p ublic A, public B 
{public 
: 
virtual void Funa () 
{ 
cout << "Funa1c" <&L T  Endl; 
}; 
}; 
int _tmain (int argc, _tchar* argv[]) 
{ 
C objc; 
A *pa = &objC; 
B *PB = &objC; 
C *pc = &objC; 
 
printf ("%d%d\n", &OBJC, OBJC); 
printf ("%d%d\n", PA, *PA); 
printf ("%d%d\n", PB, *PB); 
printf ("%d%d\n", PC, *pc); 
 
return 0; 
}

Run Result:

5241376 1563032

5241376 1563032

5241380 1563256

5241376 1563032

Careful comrade must have found PB out of the problem, why is clearly pointing to OBJC pointer, Pb and others value is different?

is the compiler out of the question?

of course not! Let's start with the conclusion:

(1) Every class that contains a virtual function will generate a virtual table (virtual tables). This table, which records the dynamic type of the object, determines which member function is actually executed when executing the virtual member function of this object.

(2) For class objects that have more than one base class, there will be multiple virtual tables, each of which corresponds to a virtual table, and the order of the virtual tables is the same as the order of the inheritance.

(3) in the memory occupied by each class object, the virtual pointer is at the front, and each virtual pointer points to the corresponding virtual table.

Start with a simple single base class:

Class A 
{public 
: 
virtual void Funa () 
{ 
cout << "FunA1" << Endl; 
virtual void FunA2 () 
{ 
cout << "FunA2" << Endl; 
} 
}; 
 
Class C:p ublic A 
{ 
virtual void Funa () 
{ 
cout << "Funa1c" << Endl; 
}
}; 
int _tmain (int argc, _tchar* argv[]) 
{ 
a *pa = new A; 
c *pc = new C; 
typedef void (*fun) (void); 
 
Fun fun= (Fun) * ((int*) (* (int*) PA)); 
Fun ();//pa point to the first function 
fun = (fun) * ((int*) (* (int*) PA) + 1); 
Fun ();//pa point to the second function 
fun = (fun) * ((int*) (* (int*) PC)); 
Fun ();//pc point to the first function 
fun = (fun) * ((int*) (* (int*) PC) + 1); 
Fun ();//pc point to the second function return 
0; 
}  

Run Result:

FunA1
FunA2
Funa1c
FunA2
Is it a little dizzy? Never mind. I explained 1.1: PA corresponds to a object of a, we can draw such a table:
      
This is the virtual table of the object *pa, and two virtual functions are arranged in a declared order. The PA points to the object *pa, then the * (int*) PA points to the virtual table, then (Fun) * (int*) (* (int*) PA) points to Funa, and similarly, (Fun) * (int*) (* (int*) PA) + 1) points to FunA2. So, there were the first two results.
Based on the latter two results, we can infer that the imaginary table of *PC is shown in the following illustration:
      
In other words, the address of a virtual function in a virtual table is rewritten because the Funa rewrite (override) in C is Funa in a.
That is, this is the internal mechanism of the polymorphic implementation.
Let's go back to the original question: Why the *PB is out of the question.
According to the above conclusion, we boldly speculate: Because C is derived from A and B, so OBJC has two virtual tables, and because of the order of the tables, the PA, the PC points to a virtual table, and the PB points to the virtual table corresponding to B. Do an experiment to verify that our conjecture is correct:
We do not change the A, B, C class, the problem of the main change:
int _tmain (int argc, _tchar* argv[]) 
{ 
C objc; 
A *pa = &objA; 
B *PB = &objC; 
C *pc = &objC; 
typedef void (*fun) (void); 
 
Fun Fun = (Fun) * ((int*) (* (int*) PC)); 
Fun ()///first Table first function 
fun = (fun) * ((int*) (* (int*) PC) +1); 
Fun ()///First table second function 
fun = (fun) * ((int*) (* ((int*) pc+1))); 
Fun (); <span style= "White-space:pre" > </span>//the first function of the second table 
fun = (fun) * ((int*) (* (int*) PB)); 
Fun ();//pb the first function of the table pointed to return 
0; 
}  

Haha, and our guess is exactly the same:

Funa1c
FunA2
Funb
Funb
We can draw such a virtual function diagram:
        
For the time being, the compiler performs B *PB = &OBJC When it is not just an assignment, but a corresponding optimization, which points the PB to the second virtual table.
Said so much, I was simply explained the virtual function of the implementation of the principle, but what is the internal memory layout of the object? What is the specific memory layout of class data members and multiple virtual tables? How did the compiler optimize when assigning values? I'll talk about it in the later time.

The above is a small series of C + + in the polymorphic and virtual functions of the internal implementation method of all content, I hope that we support cloud-Habitat Community ~

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.