“This is the seventh day of my participation in the First Challenge 2022.


Let me give you a definition: polymorphism is the ability to have many different manifestations or forms of the same behavior.

1 binding

Linking, also known as binding, is the step of “stitching” executable code together as a source program is compiled and linked into an executable file. Which is completed before the program runs known as static linking (early linking); What is done while the program is running is called dynamic linking (late linking). The polymorphism supported by static linking is called compile-time polymorphism (static polymorphism) and is implemented through function overloading or function templates; The polymorphism supported by dynamic linking is called runtime polymorphism (dynamic polymorphism) and is implemented through virtual function tables.

2 static polymorphism

2.1 Function Overloading

Let’s start with a case in code engineering:

void Swap1(int* a, int* b);
void Swap2(float* a, float* b);
void Swap3(char* a, char* b);
void Swap4(double* a, double* b);
Copy the code

When several functions with the same functions but different details are used, C language will use different function names to distinguish them, as shown in the example above. However, this not only affects the appearance, but also makes it difficult to call and code management. Function overloading was introduced in C++ : overloading allows several functions of the same name to be declared in the same scope. These functions must have different parameter lists (parameter number, type, order). It is often used to handle the problem of implementing similar functions with different data types. The above example can be rewritten in C++ as:

void Swap(int* a, int* b);
void Swap(float* a, float* b);
void Swap(char* a, char* b);
void Swap(double* a, double* b);
Copy the code

Not only functions can be overloaded in C++, but operators can also be overloaded. An operator can be thought of as a function name. For example, a+=1 can be thought of as a.+=(1), where a is the object and += is its attribute. Since operators can be viewed this way, it is natural to overload them. An example of operator overloading is as follows, where operator is the keyword that declares the operator.

void operator +=(int number);
Copy the code

2.2 Function Templates

Consider function overloading in Section 2.1. If overloaded functions differ only in their interface data types, with identical bodies and names, you can use function templates to further simplify your code.

First, the format of the function template is given:

Template <typename type parameter 1, typename type parameter 2,... Function name (parameter list){function body}Copy the code

For example, the overloaded swap function in Section 2.1 could be replaced with a function template:

template <typename T>void swap(T* a, T* b)
{
	T temp = *a;
	*a = *b;
	*b = temp;
}
Copy the code

Template and typename are keywords used to declare function templates. Any valid input data type can be processed using the above function template. It is important to note that the compiler does not support the separation of the declaration and implementation of template functions, so the body of the template function is also written in the header file.

3 Dynamic polymorphism

Dynamic polymorphism allows the parent class object to be configured with the properties of one or more derived class objects. Supported by polymorphism, an interface of a parent object performs different operations depending on the derived object.

3.1 Implementation Principle

Consider the following code engineering first.

class Father { public: virtual void func1(){ std::cout << "FUNC1:Father" << std::endl; } virtual void func2(){ std::cout << "FUNC2:Father" << std::endl; } void func3(){ std::cout << "FUNC3:Father" << std::endl; }}; class Son :public Father { public: virtual void func1(){ std::cout << "FUNC1:Son" << std::endl; } void func3(){ std::cout << "FUNC3:Son" << std::endl; }}; void testFunc(Father* ptr) { ptr->func1(); ptr->func3(); } int main() { Son* testSon = new Son; Father* testFather = new Father; STD: : cout < < "= = = = = = = = = = = = = = subclass test = = = = = = = = = = = = = \ n"; testFunc(testSon); STD: : cout < < "\ n = = = = = = = = = = = = = = parent test = = = = = = = = = = = = = \ n"; testFunc(testFather); }Copy the code

The execution results are as follows:

= = = = = = = = = = = = = = subclass test = = = = = = = = = = = = = FUNC1: Son FUNC3 - a non-class function: Father = = = = = = = = = = = = = = parent test = = = = = = = = = = = = = FUNC1: Father FUNC3 - a non-class function: FatherCopy the code

First, explain why you want to configure the parent class through subclass attributes. As shown in Figure 1, mobile hard disk, U disk and SD card are all subclasses derived from parent storage devices. In practical applications, it is only necessary to design a storage peripheral interface and determine the driver that the interface will execute by judging which peripheral is used. This interface – oriented design approach can enhance reuse and modularization, otherwise a peripheral needs to correspond to a kind of interface, too miscellaneous.

The following code results are analyzed to illustrate the realization principle of polymorphism.

The function testFunc() wants to exhibit polymorphism, and the subclass instance testSon performs func1() with subclass properties, but func3() with superclass properties — no polymorphism — because func1() is modified by the keyword virtual. The keyword virtual applies late linking, and the function modified by it is called virtual, whereas dynamic polymorphism is supported only under late linking, so only func1() shows polymorphism.

At this point, the conditions that constitute dynamic polymorphism are summarized :(a) the object calling a function must be a pointer or reference; (b) The function called must be virtual.

The late linkage realizes dynamic polymorphism through virtual function Table V-table, which is the virtual function address Table of an instance. If an instance has virtual functions, the instance’s memory is automatically allocated a virtual function table indicating which functions the instance should actually call. The virtual function pointer in the instance points to the memory location of the virtual function table.

Figure 2 shows the various types of polymorphism where the virtual function table is updated at instantiation time — complete with inheritance and overwriting, and as the program runs, the compiler looks for the virtual table to link to the functions that the instance should actually perform.

The sample code is the type of Figure 2(b), and Figure 3 shows the variable monitoring area of the sample code. It can be seen that the virtual function table of the parent class is different from that of the derived class. If the derived class overrides the virtual function, the virtual table will be updated (func1), while the virtual function that is not overridden in the parent class (func2) is still inherited by the child class.

3.2 Pure virtual functions

A pure virtual function can be represented by setting a virtual function to 0. A pure virtual function defines only the function interface. A class containing a pure virtual function is called an abstract class.

An abstract class defines a prototype of the actions that a class might emit, but it has neither implementation nor any state information. The reason for introducing abstract classes is that in many cases the base class itself does not make sense when instantiated. For example, animal as a base class can be derived from tiger, peacock and other subclasses, but the instantiation of the animal itself is meaningless, so the animal class can be defined as an abstract class.

class Animal
{
public:
	virtual void eat() = 0;
	virtual void run() = 0;
	virtual ~Animal() = default;
};
Copy the code

Because abstract classes only provide stereotypes and cannot be instantiated, derived classes must provide a concrete implementation of the interface or they cannot be instantiated.

Welcome to follow my AI channel “AI Technology Club”