Understanding of C ++ Polymorphism

Source: Internet
Author: User

The polymorphism of classes is the most important feature that supports object-oriented languages. People who have experience in non-object-oriented language development usually feel uncomfortable with the content of this chapter, many people mistakenly think that the encapsulated language of the Support class supports object-oriented. In fact, Visual BASIC 6.0 is a typical non-object-oriented development language, but it does support classes, the Support class does not indicate that it supports object-oriented languages and languages that can solve polymorphism issues are the languages that truly support object-oriented development. Therefore, you must be reminded that there are other non-object-oriented language basics!

The concept of polymorphism is a bit vague. If you want to use a clear language to describe it at the beginning, it seems unrealistic for readers to understand it, so let's look at the following code first:

// Routine 1
01
# Include <iostream>
02
Using namespace std;
03

04
Class Vehicle
05
{
06
Public:
07
Vehicle (float speed, int total)
08
{
09
Vehicle: speed = speed;
10
Vehicle: total = total;
11
}
12
Void ShowMember ()
13
{
14
Cout <speed <"|" <total <endl;
15
}
16
Protected:
17
Float speed;
18
Int total;
19
};
20
Class Car: public Vehicle
21
{
22
Public:
23
Car (int aird, float speed, int total): Vehicle (speed, total)
24
{
25
Car: aird = aird;
26
}

Void ShowMember () but in actual work, it is likely that the class of the object is unclear. Let's take a look at the example of passing a member of a derived class as a function parameter. The Code is as follows:
// Routine 2
01
# Include <iostream>
02
Using namespace std;
03

04
Class Vehicle
05
{
06
Public:
07
Vehicle (float speed, int total)
08
{
09
Vehicle: speed = speed;
10
Vehicle: total = total;
11
}
12
Void ShowMember ()
13
{
14
Cout <speed <"|" <total <endl;
15
}
16
Protected:
17
Float speed;
18
Int total;
19
};
20
Class Car: public Vehicle
21
{
22
Public:
23
Car (int aird, float speed, int total): Vehicle (speed, total)
24
{
25
Car: aird = aird;
26
}
27
Void ShowMember ()
28
{
29
Cout <speed <"|" <total <"|" <aird <endl;
30
}
31
Protected:
32
Int aird;
33
};
34
 
35
Void test (Vehicle & temp)
36
{
37
Temp. ShowMember ();
38
}
39
 
40
Void main ()
41
{
42
Vehicle a (120,4 );
43
Car B (180,110, 4 );
44
Test ();
45
Test (B );
46
Cin. get ();
47
}
In this example, object a and object B are the objects of the base class and derived class, while the form parameter of function test is only a reference of the Vehicle class. According to the characteristics of class inheritance, the system regards the Car class object as a Vehicle class object. Because the Car class covers the Vehicle class, the definition of the test function is correct, the purpose of using the test function is to pass the references of different classes of objects and call the ShowMember member functions of different classes and overload them respectively, however, the running result of the program is unexpected. The system cannot tell whether the passed base class object is a derived class object, both the base class object and the derived class object call the ShowMember member function of the base class.

01
{
02
Cout <speed <"|" <total <"|" <aird <endl;
03
}
04
Protected:
05
Int aird;
06
};
07
 
08
Void main ()
09
{
10
Vehicle a (120,4 );
11
A. ShowMember ();
12
Car B (180,110, 4 );
13
B. ShowMember ();
14
Cin. get ();
15
}
In c ++, the derived class is allowed to overload the base class member function. For Class overloading, it is clear that when different class objects call their class member functions, the system knows how to find members with the same name of the class. showMember (); that is, Vehicle: ShowMember (), B. showMember ();, that is, the Car: ShowMemeber (); is called ();.

However, in actual work, it is likely that the class to which the object belongs is unclear. Let's take a look at the example of passing a member of a derived class as a function parameter. The Code is as follows:

// Routine 2
01
# Include <iostream>
02
Using namespace std;
03

04
Class Vehicle
05
{
06
Public:
07
Vehicle (float speed, int total)
08
{
09
Vehicle: speed = speed;
10
Vehicle: total = total;
11
}
12
Void ShowMember ()
13
{
14
Cout <speed <"|" <total <endl;
15
}
16
Protected:
17
Float speed;
18
Int total;
19
};
20
Class Car: public Vehicle
21
{
22
Public:
23
Car (int aird, float speed, int total): Vehicle (speed, total)
24
{
25
Car: aird = aird;
26
}
27
Void ShowMember ()
28
{
29
Cout <speed <"|" <total <"|" <aird <endl;
30
}
31
Protected:
32
Int aird;
33
};
34
 
35
Void test (Vehicle & temp)
36
{
37
Temp. ShowMember ();
38
}
39
 
40
Void main ()
41
{
42
Vehicle a (120,4 );
43
Car B (180,110, 4 );
44
Test ();
45
Test (B );
46
Cin. get ();
47
}
In this example, object a and object B are the objects of the base class and derived class, while the form parameter of function test is only a reference of the Vehicle class. According to the characteristics of class inheritance, the system regards the Car class object as a Vehicle class object. Because the Car class covers the Vehicle class, the definition of the test function is correct, the purpose of using the test function is to pass the references of different classes of objects and call the ShowMember member functions of different classes and overload them respectively, however, the running result of the program is unexpected. The system cannot tell whether the passed base class object is a derived class object, both the base class object and the derived class object call the ShowMember member function of the base class.

To solve the problem that object types cannot be correctly identified, c ++ provides a technology called polymorphism to solve the problem. For example, during compilation, this method can determine which overloaded member function is called as early binding. When the system is able to run, the ability to determine which overloaded member function can be called based on its type, which is called Polymorphism or late binding. The following is the example 3: lagging concatenation, delayed Association is the solution to the problem of polymorphism.

The Code is as follows:

// Example 3
01
# Include <iostream>
02
Using namespace std;
03

04
Class Vehicle
05
{
06
Public:
07
Vehicle (float speed, int total)
08
{
09
Vehicle: speed = speed;
10
Vehicle: total = total;
11
}
12
Virtual void ShowMember () // virtual function
13
{
14
Cout <speed <"|" <total <endl;
15
}
16
Protected:
17
Float speed;
18
Int total;
19
};
20
Class Car: public Vehicle
21
{
22
Public:
23
Car (int aird, float speed, int total): Vehicle (speed, total)
24
{
25
Car: aird = aird;
26
}
27
Virtual void ShowMember () // virtual function. In the derived class, because of the inheritance relationship, the virtual
28
{
29
Cout <speed <"|" <total <"|" <aird <endl;
30
}
31
Public:
32
Int aird;
33
};
34
 
35
Void test (Vehicle & temp)
36
{
37
Temp. ShowMember ();
38
}
39
 
40
Int main ()
41
{
42
Vehicle a (120,4 );
43
Car B (180,110, 4 );
44
Test ();
45
Test (B );
46
Cin. get ();
47
}
The job dependency of the polymorphism feature is defined by the virtual function. When the virtual keyword is added before the overloaded member function to solve the polymorphism problem, the member function becomes a virtual function, from the result of running the code in the preceding example, the system successfully identifies the real type of the object and successfully calls their respective overloaded member functions.

The polymorphism feature saves programmers the consideration of details, improves development efficiency, and greatly simplifies code. Of course, the definition of virtual functions is also flawed, because the polymorphism feature increases the overhead of data storage and command execution, it is best not to use polymorphism.

 

The definition of virtual functions follows the following important rules:

1. if a virtual function appears in a base class and a derived class, it only has the same name, and the form parameter is different, or the return type is different, even if the virtual keyword is added, it will not be delayed.

2. Only member functions of a class can be described as virtual functions. Because Virtual functions are only suitable for class objects with inheritance relationships, common functions cannot be described as virtual functions.

3. static member functions cannot be virtual functions, because static member functions are not restricted to an object.

4. the inline function cannot be a virtual function, because the inline function cannot dynamically determine the position during running. Even if a virtual function is defined within a class, the system still regards it as non-inline during compilation.

5. the constructor cannot be a virtual function, because during the construction, the object is still a space with a fixed position. Only after the construction is complete, the object is an instance of a specific class.

6. destructor can be virtual functions and are generally known as virtual functions.

Although we say that using virtual functions reduces efficiency, it is always advantageous to define all member functions in a class as virtual functions as the processing speed is getting faster and faster, in addition to adding some additional overhead, it has no other disadvantages and is good for ensuring the encapsulation characteristics of classes.

For the important rule 6 used by the above virtual functions, it is necessary to use an instance to explain why the destructor of classes with polymorphism features should be declared as virtual.

The Code is as follows:

01
# Include <iostream>
02
Using namespace std;
03

04
Class Vehicle
05
{
06
Public:
07
Vehicle (float speed, int total)
08
{
09
Vehicle: speed = speed;
10
Vehicle: total = total;
11
}
12
Virtual void ShowMember ()
13
{
14
Cout <speed <"|" <total <endl;
15
}
16
Virtual ~ Vehicle ()
17
{
18
Cout <"loading Vehicle-based class destructor" <endl;
19
Cin. get ();
20
}
21
Protected:
22
Float speed;
23
Int total;
24
};
25
Class Car: public Vehicle
26
{
27
Public:
28
Car (int aird, float speed, int total): Vehicle (speed, total)
29
{
30
Car: aird = aird;
31
}
32
Virtual void ShowMember ()
33
{
34
Cout <speed <"|" <total <"|" <aird <endl;
35
}
36
Virtual ~ Car ()
37
{
38
Cout <"loading Car derived class destructor" <endl;
39
Cin. get ();
40
}
41
Protected:
42
Int aird;
43
};
44
 
45
Void test (Vehicle & temp)
46
{
47
Temp. ShowMember ();
48
}
49
Void DelPN (Vehicle * temp)
50
{
51
Delete temp;
52
}
53
Void main ()
54
{
55
Car * a = new Car (100,1, 1 );
56
A-> ShowMember ();
57
DelPN ();
58
Cin. get ();
59www.2cto.com
}
From the running results of the preceding Code, when DelPN (a); is called, the system successfully determines that the Car class destructor is called first, if you remove the virtual modifier of The Destructor and observe the result, you will find that the destructor of the base class is always called, the virtual modifier of polymorphism is not only necessary for common member functions of the base class and the derived class, but also important for the destructor of the base class and the derived class.


Author: Chen jiexin

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.