Prelude
There are endless questions about virtual functions, and articles about virtual functions are the same. Why should I write this article on virtual functions? After reading this article, I believe I can understand its meaning. At the same time, the original fantasy series has changed its name to the programmer's programming Art Series, because it no longer focuses only on "interview", but on "programming. OK. If there are any errors, please kindly advise. Thank you.
Section 1: A simple questions about virtual functions
Question requirement: Write the running result of the following program?
View plaincopy to clipboardprint?
// Thank you for providing this Baidu interview question
# Include <iostream>
Using namespace std;
Class
{
Public:
Virtual void p ()
{
Cout <"A" <endl;
}
};
Class B: public
{
Public:
Virtual void p ()
{
Cout <"B" <endl;
}
};
Int main ()
{
A * a = new;
A * B = new B;
A-> p ();
B-> p ();
Delete;
Delete B;
Return 0;
}
// Thank you for providing this Baidu interview question
# Include <iostream>
Using namespace std;
Class
{
Public:
Virtual void p ()
{
Cout <"A" <endl;
}
};
Class B: public
{
Public:
Virtual void p ()
{
Cout <"B" <endl;
}
};
Int main ()
{
A * a = new;
A * B = new B;
A-> p ();
B-> p ();
Delete;
Delete B;
Return 0;
}
I think this interview question should be a relatively simple question about the knowledge of virtual functions. Then, I hope that you will encounter this kind of questions about virtual functions. Whether it is difficult or easy, you will be able to draw a line from each other. Then the purpose of this chapter will be achieved. OK. Please follow my ideas and proceed step by step (the output result of the above program is a B ).
Section 2: differences between functions with or without virtual functions
1. When FUNCTION p () in the above program is not a virtual function, what is the running result of the program? The following code is used:
Class
{
Public:
Void p ()
{
Cout <"A" <endl;
}
};
Class B: public
{
Public:
Void p ()
{
Cout <"B" <endl;
}
};
Right, the program will output two A, A at this time. Why?
We know that when constructing a class object, if it has a base class, we will first construct the base class object and then construct the own object of the derived class. As shown above, A * a = new A, call the default constructor to construct the base class A object, and then call the function p (), a-> p (); Output A, which is no problem.
Then, A * B = new B; constructs the derived class object B. Because B is A derived class Object of the base class A, the base class A object is constructed first, then construct the derived class object. However, when the function in the program is called as a non-virtual function, the Class B object's call to function p () has been statically determined during compilation, no matter whether base class pointer B finally points to a base class object or a derived class object, as long as the function called by the following object is not a virtual function, it will be ignored directly, instead, call the p () function of the Base Class.
2. What if I add a virtual function? What is the output result of the program, as in the first program?
Before that, we have to clarify the following two points:
A. When a function defined in the base class is called through a base class reference or pointer, we do not know the exact type of the object that executes the function. The object that executes the function may be of the base class type, it may also be a derived type.
B. If a non-virtual function is called, the function defined by the base class type is executed no matter what type of the actual object is (as described in the preceding 1st points ). If you call a virtual function, you cannot determine which function to call until the runtime. The running virtual function references the version of the Type Definition of the object to which the bound or Pointer Points.
Based on the above B's point of view, we know that if we add a virtual function, as shown in the above question,
Class
{
Public:
Virtual void p ()
{
Cout <"A" <endl;
}
};
Class B: public
{
Public:
Virtual void p ()
{
Cout <"B" <endl;
}
};
Int main ()
{
A * a = new;
A * B = new B;
A-> p ();
B-> p ();
Delete;
Delete B;
Return 0;
}
The output result of the program is a B.
So far, our questions have been solved. However, the problem of virtual functions has not been solved yet.
Section 3: Principles and nature of virtual functions
We already know that the general implementation model of virtual functions is: each class has a virtual table, which contains the virtual tables that are useful in this class) function address, and each object has a vptr pointing to the virtual table.
Let me cite an example from the book "Deep Exploration of c ++ object models:
Class Point {
Public:
Virtual ~ Point ();
Virtual Point & mult (float) = 0;
Float x () const {return _ x;} // non-virtual function, not stored
Virtual float y () const {return 0 ;}
Virtual float z () const {return 0 ;}
//...
Protected:
Point (float x = 0.0 );
Float _ x;
};
1. In the Point Object pt, there are two things: one is data member _ x and the other is _ vptr_Point. _ Vptr_Point points to virtual table point, while virtual table point stores the following:
Virtual ~ Point () is assigned slot 1,
Mult () will be assigned slot 2.
Y () is will be assigned slot 3
Z () will be assigned slot 4.
Class Point2d: public Point {
Public:
Point2d (float x = 0.0, float y = 0.0)
: Point (x), _ y (y ){}
~ Point2d (); // 1
// Rewrite base class virtual functions
Point2d & mult (float); // 2
Float y () const {return _ y;} // 3
Protected:
Float _ y;
};
2. In the object pt2d of Point2d, there are three things: First inherited from the data member _ x of the base class pt object, and then the data member _ y of the pt2d object, finally, it is _ vptr_Point. _ Vptr_Point points to virtual table point2d. Because Point2d inherits from the Point, ~ Point2d (), Point2d & mult (float), float y () const, and Point: z () functions that have not been rewritten.
Class Point3d: public Point2d {
Public:
Point3d (float x = 0.0,
Float y = 0.0, float z = 0.0)
: Point2d (x, y), _ z (z ){}
~ Point3d ();
// Overridden base class virtual functions
Point3d & mult (float );
Float z () const {return _ z ;}
//... Other operations...
Protected:
Float _ z;
};
3. In the object pt3d of Point3d, there are four things: _ x, _ vptr_Point, _ y, and _ z. _ Vptr_Point points to virtual table point3d. Because point3d inherits from point2d, it stores ~ Point3d (), point3d: the address of the mult () function, the address of the z () function, and the address of the y () function of point2d that has not been rewritten.
OK. For details about all the situations above, see.
(Figure: virtual table layout: single inheritance)
This article may consider adding relevant content as appropriate in the future. OK. For more information, see chapter 4 of in-depth exploration of the c ++ object model.
In the past few chapters, the difficulty is relatively small. It is due to the deep and shallow concept of fantasy, and the subsequent chapters will gradually become more difficult.
Section 4: virtual function layout and assembly
Ivan and old dream continue