In C ++, polymorphism refers to addressing a derived class object with a base class pointer or reference. Virtual member function is the basis of polymorphism, which is also a fascinating aspect of object-oriented programming. Now we have time to write down our superficial understanding of how C ++ implements virtual functions in the case of a single inheritance.
Once a class has a virtual function, a virtual table will be created. The virtual table contains the addresses of all virtual functions. A virtual table is shared by all objects in this class. Each object has a virtual pointer (vptr) pointing to the virtual table. Virtual pointer setting and resetting are automatically completed by the class constructor, destructor, and copy assignment operator.
Virtual tables are the basis of virtual functions. A table has many slots. Generally, the first slot stores the type information (type_info object) associated with each class to support RTTI ).
[Cpp]
Class Demo {
Public:
Demo ();
Virtual ~ Demo ();
Virtual void f1 ();
Virtual void f2 ();
Void f3 ();
Static void f4 ();
Private:
Static int ival;
Long lval;
};
Class Demo {
Public:
Demo ();
Virtual ~ Demo ();
Virtual void f1 ();
Virtual void f2 ();
Void f3 ();
Static void f4 ();
Private:
Static int ival;
Long lval;
};
Figure 1 Demo class Object Memory Layout
Non-static member variables and virtual pointers are stored inside each object, and other Members are stored outside the object.
In C ++, virtual functions are known between compilers, and the addresses of these virtual functions are fixed and cannot be added or replaced during the execution period. To locate the function address, each virtual function has an index number in the virtual table.
If the derived class decides not to rewrite a virtual function during the process of inheriting the base class, it will inherit the entity (Definition) of the base class function, the function of the base class is stored in the virtual table of this derived class. Otherwise, if the derived class overrides a virtual function of the base class, the virtual table of the derived class will store the entity that is redefined for this virtual function. As shown in.
[Cpp]
Class Base {
Public:
Virtual void x ();
Virtual void y ();
Int ival;
};
// Single inheritance
Class Derived: public Base {
Public:
Void x ();
Virtual void z ();
Long lval;
};
Class Base {
Public:
Virtual void x ();
Virtual void y ();
Int ival;
};
// Single inheritance
Class Derived: public Base {
Public:
Void x ();
Virtual void z ();
Long lval;
};
Figure 2 virtual table under single inheritance
Note:
1) if it is a virtual function entity that inherits the declaration of the base class, the function entity will be copied to the slot corresponding to the virtual table of the derived class.
2) if you use your own function entity, that is, to rewrite the virtual function of the base class, you must also place the function entity address in the corresponding slot.
3) if a new virtual function is added, a slot will be added to the virtual table, and the new virtual function entity will be put here.
Therefore, for the above example, we have the following usage:
[Cpp]
Ptr-> x ();
Ptr-> x (); we do not know whether ptr is a Base or Dervied pointer, so we cannot obtain the virtual table of this object by ptr. However, I know every x () the address of the function will be placed in the #1 slot, so the compiler will convert the call
[Cpp]
(* Ptr-> vptr [1]) (ptr );
(* Ptr-> vptr [1]) (ptr); in the above expression, the only thing that needs to be known during the execution period is the type of virtual table of Slot 1, once you know, you can call the corresponding function body.
Write it here.
Under Multi-inheritance and virtual inheritance, the implementation of virtual functions is not that easy. Please write it later.