Introduction
I have never written a conceptual article, because I think it is useless to write these conceptual things in detail in books, today, I want to write a piece of whimsy. I will discuss with you the virtual base classes, virtual functions, and pure virtual functions. It is easy to get confused when you look at the name. But it doesn't matter. You will understand it after reading this article.
Body
Virtual base class
Let's take a look at a piece of code before explaining its role.
Class
{
Public:
Int ivalue;
};
Class B: public
{
Public:
Void bprintf () {cout <"this is Class B" <Endl ;};
};
Class C: public
{
Public:
Void cprintf () {cout <"this is Class C" <Endl ;};
};
Class D: Public B, public C
{
Public:
Void dprintf () {cout <"this is Class D" <Endl ;};
};
Void main ()
{
D;
Cout <D. ivalue <Endl; // error, ambiguous access
Cout <D. A: ivalue <Endl; // correct
Cout <D. B: ivalue <Endl; // correct
Cout <D. C: ivalue <Endl; // correct
}
From the code, we can see that class B c inherits the ivalue members of Class A, so Class B c has a member variable ivalue, and Class D inherits B C, in this way, Class D has a duplicate member ivalue (one inherited from Class B and the other inherited from Class C ). call D in the main function. ivalue the ivalue compiler has a duplicate member in Class D and does not know who calls the ivalue inherited from it. the correct method should be to add the scope qualifier D. b: ivalue indicates the ivalue inherited from Class B. However, instances of class D have multiple ivalue instances, which occupy the memory space. Therefore, the concept of the virtual base class is referenced in C ++ to solve this problem.
Class
{
Public:
Int ivalue;
};
Class B: virtual public
{
Public:
Void bprintf () {cout <"this is Class B" <Endl ;};
};
Class C: virtual public
{
Public:
Void cprintf () {cout <"this is Class C" <Endl ;};
};
Class D: Public B, public C
{
Public:
Void dprintf () {cout <"this is Class D" <Endl ;};
};
Void main ()
{
D;
Cout <D. ivalue <Endl; // correct
}
Add the virtual keyword before the inherited class to indicate that the inherited class is a virtual base class, and its inherited members keep only one instance in the derived class. For example, from the perspective of class D, ivalue is inherited from class B and class C, while Class B C is inherited from Class, but they only keep one copy. Therefore, errors will not occur when calling d. ivalue in the main function.
Virtual Functions
Check the code first.
Class
{
Public:
Void funprint () {cout <"funprint of Class A" <Endl ;};
};
Class B: public
{
Public:
Void funprint () {cout <"funprint of Class B" <Endl ;};
};
Void main ()
{
A * P; // defines the pointer of the base class.
A;
B;
P = &;
P-> funprint ();
P = & B;
P-> funprint ();
}
What do you think is the output result of this code? Some people may immediately reply to funprint of Class A and funprint of Class B because the first output references the instance of Class A and the second output references the instance of Class B. The answer is: funprint of Class A and funprint of Class A. As for why the output is not within the scope of this article, remember, no matter which class the referenced instance belongs to, the system will call the method of the class of the object with the left value when you call it. For example, the above Code Class a B has a funprint function, because P is a Class A pointer, no matter whether you direct the P pointer to Class A or Class B, the final called functions are all funprint functions of Class. This is the static link, and the compiler has determined it during compilation. But what if I want to dynamically decide which function to call different from the data instance? This requires virtual functions (that is, dynamic join)
Class
{
Public:
Virtual void funprint () {cout <"funprint of Class A" <Endl ;};
};
Class B: public
{
Public:
Virtual void funprint () {cout <"funprint of Class B" <Endl ;};
};
Void main ()
{
A * P; // defines the pointer of the base class.
A;
B;
P = &;
P-> funprint ();
P = & B;
P-> funprint ();
}
Add the virtual keyword before the member function of the base class to indicate that this function is a virtual function. The so-called virtual function is not sure which function to call during compilation, instead, it dynamically determines the function to be called. To implement a virtual function, the function name of the derived class must be the same as that of the base class, and the parameter type of the parameter name must also be the same as that of the base class. However, the virtual keyword in the derived class can be omitted, which also indicates that this is a virtual function. The following Code declares a pointer to a base class (must be a base class, otherwise not) P, Points P to instance a of Class A, and calls the funprint function, in this case, the system determines the type of the instance pointed to by P. If the instance belongs to Class A, the system calls the funprint function of Class, if it is a Class B instance, call the funprint function of Class B.
Pure virtual functions
It is better to call a pure virtual function than an abstract class. It just declares a function but does not implement it, so that the derived class can implement it. In fact, this is quite understandable.
Class Vehicle
{
Public:
Virtual void printtyre () = 0; // The pure virtual function is defined as follows:
};
Class camion: Public Vehicle
{
Public:
Virtual void printtyre () {cout <"camion tyre four" <Endl ;};
};
Class bike: Public Vehicle
{
Public:
Virtual void printtyre () {cout <"bike tyre two" <Endl ;};
};
Void main ()
{
Camion C;
Bike B;
B. printtyre ();
C. printtyre ();
}
The above Code defines a vehicle class (vehicle). There is a function in the class that can print the number of tires of the vehicle, but the number of tires of many vehicles is naturally not certain, therefore, it is defined as a pure virtual function, that is, the light-defined function name does not implement it. The camion class inherits vehicle and implements the code in it, printing out four tires. The same is true for bike classes. Note that pure virtual functions cannot be implemented, but pointers can be declared.
Summary
Virtual base class
1. A class can be used as either a virtual base class or a non-virtual base class in a class family.
2. In a derived class object, a virtual base class with the same name only produces one virtual base class sub-object, while a non-virtual base class generates its own sub-object.
3. The virtual base class sub-object is initialized by the constructor of the most derived class by calling the constructor of the virtual base class.
4. The most derived class is the class specified when an object is created in the inheritance structure.
5. The member initialization list of the constructor of the derived class must list the calls to the constructor of the virtual base class. If not, the default constructor of the virtual base class is used.
6. The call to the virtual base class constructor must be listed in the constructor initialization list of the derived class directly or indirectly derived from the virtual base class. However, only constructors used to create the most derived class of an object call the constructors of the virtual base class, the call to the constructor of the virtual base class listed in all base classes of the derived class is ignored during execution, so as to ensure that the sub-objects of the virtual base class are initialized only once.
7. When you call both the virtual and non-virtual base constructors in the member initialization list, the constructors of the virtual base class are executed before the constructors of the non-virtual base class.
Virtual Functions
1. virtual functions are non-static, non-inline member functions, but not friend functions. However, virtual functions can be declared as friend functions in another class.
2. The virtual function declaration can only appear in the class-defined function prototype declaration, but cannot be declared when the function body of the member function is implemented.
3. No matter how many times a virtual function is inherited by the public, it still maintains the features of its virtual function.
4. If a member function in the class is described as a virtual function, the member function may have different implementations in the derived class. When this member function is used to operate a pointer or reference the identified object, dynamic association can be used for calling this member function.
5. After a virtual function is defined, the pointer declared in the program to the base class can point to its derived class. During execution, the function can constantly change the objects it points to, call member functions of different versions, and these actions are dynamically implemented at runtime. Virtual functions fully reflect the dynamic polymorphism of object-oriented programming. Pure virtual function version member functions, and these actions are dynamically implemented at runtime. Virtual functions fully reflect the dynamic polymorphism of object-oriented programming.
Pure virtual functions
1. When the base class cannot provide a meaningful implementation for the virtual function, you can declare it as a pure virtual function, and its implementation will be left for the completion of the derived class.
2. The pure virtual function provides a consistent interface for the derived class.
3. Pure virtual functions cannot be implemented, but pointers can be declared.