Polymorphism of classes and use of virtual functions in C ++
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 language that supports class encapsulation supports object-oriented,
Visual
Basic 6.0 It is a typical non-object-oriented development language, but it is indeed a Support class. The support class cannot be described as a language that supports object-oriented and can solve polymorphism problems, it is a language that truly supports object-oriented development. Therefore, be sure to remind readers of 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 take a look at the following: Code : // Routine 1
# Include <iostream >
Using Namespace STD;
Class Vehicle
{
Public :
Vehicle (float Speed, int Total)
{
Vehicle: speed = speed;
Vehicle: Total = total;
}
Void Showmember ()
{
Cout <Speed <"|" <total <Endl;
}
Protected :
Float Speed;
Int Total;
};
Class Car: Public Vehicle
{
Public :
Car (int AIRD, float Speed, int Total): Vehicle (speed, total)
{
Car: AIRD = AIRD;
}
Void Showmember ()
{
Cout <Speed <"|" <total <"|" <AIRD <Endl;
}
Protected :
Int AIRD;
};
Void Main ()
{
Vehicle A (120,4 );
A. showmember ();
Car B (180,110, 4 );
B. showmember ();
CIN . Get ();
}
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
# Include <iostream >
Using Namespace STD;
Class Vehicle
{
Public :
Vehicle (float Speed, int Total)
{
Vehicle: speed = speed;
Vehicle: Total = total;
}
Void Showmember ()
{
Cout <Speed <"|" <total <Endl;
}
Protected :
Float Speed;
Int Total;
};
Class Car: Public Vehicle
{
Public :
Car (int AIRD, float Speed, int Total): Vehicle (speed, total)
{
Car: AIRD = AIRD;
}
Void Showmember ()
{
Cout <Speed <"|" <total <"|" <AIRD <Endl;
}
Protected :
Int AIRD;
};
VoidTest (Vehicle & temp)
{
Temp. showmember ();
}
Void Main ()
{
Vehicle A (120,4 );
Car B (180,110, 4 );
Test ();
Test (B );
CIN . Get ();
}
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 class objects and call the showmember member functions of different classes, which are overloaded, Program The running result 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 the object type cannot be correctly identified, C ++ provides Polymorphism (Polymorphism) technology to solve the problem. For example program 1, this can determine which overloaded member function is called during compilation. Called Joint preparation (Early binding), while the system can determine which overloaded member function to call based on its type at runtime. , Called Polymorphism , Or Lagging Compilation (Late
Binding). The following figure shows the Example 3: delayed Association. Delayed Association is the solution to the problem of polymorphism.
The Code is as follows:
// Example 3
# Include <iostream >
Using Namespace STD;
Class Vehicle
{
Public :
Vehicle (float Speed, int Total)
{
Vehicle: speed = Speed;
Vehicle: Total = Total;
}
Virtual Void Showmember () // virtual function
{
Cout <Speed <"|" <total <Endl;
}
Protected :
Float Speed;
Int Total;
};
Class Car: Public Vehicle
{
Public :
Car (int AIRD, float Speed, int Total): Vehicle (speed, total)
{
Car: AIRD = AIRD;
}
Virtual Void Showmember () // virtual function. In the derived class, the virtual function can be left empty due to the inheritance relationship.
{
Cout <Speed <"|" <total <"|" <AIRD <Endl;
}
Public :
Int AIRD;
};
VoidTest (Vehicle & temp)
{
Temp. showmember ();
}
IntMain()
{
Vehicle A (120,4 );
Car B (180,110, 4 );
Test ();
Test (B );
CIN. Get ();
}
Definition of virtual functions on which polymorphism features workAddVirtualKeyword, 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, the respective overload member functions are successfully called.
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 preceding virtual function, it is necessary to describe it with an instance,It is necessary to declare the destructor of classes with polymorphism as virtual.
The Code is as follows:
# Include <iostream >
Using Namespace STD;
Class Vehicle
{
Public :
Vehicle (float Speed, int Total)
{
Vehicle: speed = speed;
Vehicle: Total = total;
}
Virtual Void Showmember ()
{
Cout <Speed <"|" <total <Endl;
}
Virtual ~ Vehicle ()
{
Cout <"Loading vehicle basic class destructor" <Endl;
CIN . Get ();
}
Protected :
Float Speed;
Int Total;
};
Class Car: Public Vehicle
{
Public :
Car (int AIRD, float Speed, int Total): Vehicle (speed, total)
{
Car: AIRD = AIRD;
}
Virtual Void Showmember ()
{
Cout <Speed <"|" <total <"|" <AIRD <Endl;
}
Virtual ~ Car ()
{
Cout <"Loading car derived class destructor" <Endl;
CIN . Get ();
}
Protected :
Int AIRD;
};
void test (Vehicle & temp)
{< br> temp. showmember ();
}< br> void delpn (Vehicle * temp)
{< br> Delete temp;
}< br> void main ()
{< br> Car * A = new Car (100,1, 1);
A-> showmember ();
delpn ();
CIN . get ();
}< br> from the running result of the preceding Code, when delpn (a); is called, the system successfully confirmed that the car class destructor should be called first. If the virtual modifier of The Destructor is removed, and then the result is observed, the system will find that, we have always called only the destructor of the base class. As a result, we find that the virtual modifier of the polymorphism feature is not only necessary for the common member functions of the base class and the derived class, it is equally important for the destructor of the base class and the derived class.