Playing a bad C + + polymorphic mechanism

Source: Internet
Author: User

Object-oriented three characteristics, encapsulation inheritance polymorphism, well, when the object-oriented encounter pointer, there is C + +. The encapsulation inheritance of the three characteristics is easy to understand, according to the author's personal understanding, encapsulation inheritance is for polymorphism and born. When a parent class has multiple inheriting classes, it is possible to invoke the inheritance function in the inheriting class flexibly by assigning the parent pointer to an object of different inheriting classes, which is polymorphic.

Virtual functions are an important element in the implementation of polymorphism, see:

classa{ Public:    voidA0 () {cout <<"A0"<<Endl;} Virtual voidA1 () {cout <<"A1"<<Endl;}};classB: Publica{ Public:    voidA0 () {cout <<"b.a0"<<Endl;}; voidA1 () {cout <<"b.a1"<<Endl;};}; Main () {A* a0 =NewB (); A0-a0 (); A0-A1 (); A A1=B ();    A1.a0 (); A1.A1 ();
Delete A;
}

The output is A0, b.a1, A0, A1. Two points: one, C + + polymorphism is implemented by pointers, which is different from Java through type conversion (called Boxing and Unboxing in C #), because when you execute a a1=b (), the B de constructor is first called to construct a B object, and then a copy constructor is called A, so The final call is the copy constructor of a, and the function of a is also called when the function is called, and second, when the function of virtual is to use polymorphism, a function with the same name and parameters of the subclass overrides the parent function, whereas for a non-virtual function, in C + +, when the member function is called through the object, The entry of a function is statically determined at compile time, and the compiler does not care what object the pointer points to when it is assigned.

All of this comes from the virtual function table mechanism of C + +. A virtual function table is a contiguous memory space that holds a series of virtual function pointers. When constructing a sub-object, the first 4B of the memory space holds the entry address of a virtual function table. As in the above example, the virtual function table for a <a::a1>,b inherits a and the virtual function A1, so the virtual function table of B is <b::a1>, that is, at the time of inheritance, the address of A::A1 is overwritten with the B::A1 function address. The following code is then available:

classa{ Public:    voidA0 () {cout <<"A0"<<Endl;} Virtual voidA1 () {cout <<"A1"<<Endl;} Virtual voidA2 () {cout <<"A2"<<Endl;}};classB: Publica{ Public:    voidA0 () {cout <<"b.a0"<<Endl;}; voidA1 () {cout <<"b.a1"<<Endl;}; voidA2 () {cout <<"b.a2"<<Endl;}}; Typevoid( *Function) (); main () {A* A =NewB (); Function P=  (void(*) (void))*( (int*) *(int*) (a) +0 );    P (); Delete A;}

which

A is the address of the object,

(int *) A is the address at the beginning of the object 4 bytes

* (int *) A is the first 4 bytes of the object

(int *) * (int *) A is the first four bytes of an object, which is actually an address, what is the address, which is the address of the virtual function table

* (int *) * (int *) A is the first item of a virtual function table, which is the address of the first virtual function, so +0 represents the first function, +1 represents the second function, and so on

Thus, through the function pointer p, the first virtual inheritance function A1 of B was successfully accessed. The virtual function table is one such thing. Here are two little tricks to come.

1, access to private functions of subclasses through function pointers

2, accessing the private function of the parent class through a function pointer

classa{Virtual voidA0 () {printf ("a::a0 (private) \ n"); } Public:    ExplicitA () {}Virtual voidA1 () {printf ("a::a1 (public) \ n"); }};classD | Publica{ Public:    ExplicitB () {}Private:    inty; Virtual voidA1 () {printf ("b::a1 (private) \ n"); }};typedefvoid(*Function) (); main () {A* A =NewB ();    Function p; P= (void(*) (void) ) *( (int*)  *(int*) (a) +0 );    P (); P= (Function) * ((int*) *(int*) (a) +1 ); P ();
A->A1 (); Delete A;}

Where A's virtual function table is <private a::a0, public a::a1> B's virtual function table is <private a::a0, private b::a1>.

P points to private a::a0 on the first call, and p to private b::a1 when the second call occurs. The check for permissions is in the compile phase, so a dynamic pointer call bypasses the permission check.

At the third invocation (A->A1 ()), because the check for permissions is in the compile phase, and the compiler does not check exactly what object A is pointing to (because it is dynamic), look only at the type of a. The compiler finds that a is a pointer to a, and A1 () is a public function in Class A, so permission checks pass smoothly. The execution then begins, at which point the pointer to A->A1 () points to b::a1 (), and we successfully invoke the private function of subclass B with the parent pointer, a * a.

Playing a bad C + + polymorphic mechanism

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.