From: http://www.cnblogs.com/chio/archive/2007/09/10/888260.html
I. Virtual destructor
We know that in order to correctly call the object's destructor, a top-level class with a hierarchy is generally required to define its destructor as a virtual function. When deleting an abstract class pointer, you must use a virtual function to find the true destructor.
For example, class base
{
Public:
Base (){}
Virtual ~ Base (){}
};
Class derived: public Base
{
Public:
Derived (){};
~ Derived (){};
}
Void Foo ()
{
Base * pb;
PB = new derived;
Delete Pb;
}
This is the correct usage and will be dynamically bound. It will first call the derived destructor, and then the base destructor
If the Destructor is not virtual, delete Pb only executes the destructor of the base, rather than the real derived destructor.
Because it is not a virtual function, the called function depends on the static type, that is, the base
Ii. Pure virtual destructor
The problem now is that we want to make base an abstract class and cannot directly construct objects. We need to define a pure virtual function in it. If there are no other suitable functions, you can define the Destructor as pure virtual, and change the previous cobject definition to: class base.
{
Public:
Base (){}
Virtual ~ Base () = 0
}; However, this Code cannot be compiled. It is usually a link error and cannot be found ~ Base () Reference (GCC Error Report ). This is because the Destructor and constructor are different from other internal functions. During calls, the compiler needs to generate a call chain. That is, the derived destructor implicitly calls the base destructor. In the code just now, ~ is missing ~ Of course, an error will occur in the base () function body.
Some people think that the pure virtual function syntax such as virtual F () = 0 does not define the semantics of the body.
In fact, this is not correct. This syntax only indicates that this function is a pure virtual function. Therefore, this class becomes an abstract class and cannot generate objects. We can specify the function body for pure virtual functions.
Http://www.research.att.com /~ BS/bs_faq2.html # Pure-virtual ). Generally, pure virtual functions do not need function bodies, because we generally do not call this function of the abstract class and only call the corresponding function of the derived class. In this way, we have a pure virtual destructor function body, and the above code needs to be changed to: class base
{
Public:
Base ()
{
}
Virtual ~ Base () = 0; // pure virtual
};
Base ::~ Base () // function body
{
}
From the syntax perspective, you cannot directly write the preceding destructor into the class declaration (writing inline functions ). This may be an unorthogonal place. However, this is indeed a little cumbersome.
This problem seems to be somewhat academic, because generally we can find a more suitable function in the base, by defining it as a pure virtual function that does not implement the body, define the entire class as an abstract class. But this technology also has some applications, such as this example: class base // abstract class
{
Public:
Virtual ~ Base () {}; // virtual, not pure
Virtual void hiberarchy () const = 0; // pure virtual
};
Void base: hiberarchy () const // pure virtual also can have function body
{
STD: cout <"base: hiberarchy ";
}
Class derived: public Base
{
Public:
Derived (){}
Virtual void hiberarchy () const
{
CB: hiberarchy ();
STD: cout <"derived: hiberarchy ";
}
Virtual void Foo (){}
};
Int main (){
Base * pb = new derived ();
Pb-> hiberarchy ();
Pb-> base: hiberarchy ();
Return 0;
}
In this example, we try to print the class inheritance relationship. Define the virtual function hiberarchy in the base class, and then reload the function in each derived class. As we can see again, to make base an abstract class, no other method Member in this class can be defined as pure virtual, we have to define hiberarchy as pure virtual. (Of course, it can be fully defined ~ Base function, which is the same as discussed above. ^_^)
In addition, we can see that there are two calling methods in Main. The first method is a normal method. We can perform dynamic linking and execute virtual functions. The result is "derived: hiberarchy "; the second method is to specify the class, so that the dynamic link process of the virtual function is no longer executed. The result is "base: hiberarchy ".
The above analysis shows that,The real purpose of defining pure virtual functions is to define abstract classes.But not the function itself. In contrast, in Java, the syntax for defining abstract classes is abstract class, that is, it is specified at the class level (of course, the abstract keyword must also be added to the virtual function ). Is this method better? In stroustrup's "design and evolution of C ++ language", I found this article:
"I chose to describe individual functions as pure virtual functions, instead of defining the complete class declaration as an abstract form, because the concept of pure virtual functions is more flexible. I really valued the ability to define classes in stages. That is to say, I found it useful to define some pure virtual functions in advance and leave others to further derived classes for definition ".
I have not fully understood the last sentence. I want to explain this concept from another perspective. That is, in a multi-layer complex class structure, classes at the intermediate level should be specific to some abstract functions, but most likely not all. The intermediate class does not need to know whether all virtual functions are embodied, and which functions have been embodied by its ancestor. You only need to pay attention to your responsibilities. That is to say, the intermediate class does not need to know whether it is a real abstract class, so the designer does not need to consider whether to add a description similar to abstract at the class level of the intermediate class.
Of course, there are many factors in the design of a language. This is just an explanation.
Finally, we will summarize some common questions about virtual functions:
1) virtual functions are dynamically bound. That is to say, you can use the pointer and reference of the virtual function to correctly find the corresponding function of the actual class, rather than executing the function that defines the class. This is the basic function of a virtual function and will not be explained.
2)The constructor cannot be a virtual function.. And,Call a virtual function in the constructor. The actual execution is the corresponding function of the parent class.Because they have not been constructed, polymorphism is disable.
3)The Destructor can be a virtual function.And, in a complex class structure, this is often necessary.
4) define a function as a pure virtual function. In fact, this class is defined as an abstract class and objects cannot be instantiated.
5)Pure virtual functions are usually not defined, but they can also have.
6) destructor can be purely virtual,The pure virtual destructor must have a definition body.Because the Destructor are called in the subclass.
7) Non-pure virtual functions must have definitions. Otherwise, this is an error.
8) the override virtual function definition of the derived class must be exactly the same as that of the parent class.Except for a special case, if the returned value in the parent class is a pointer or reference, the subclass override can return the derivation of this pointer (or reference ).. For example, in the above example, virtual base * clone () is defined in the base; In derived, it can be defined as virtual derived * clone (). We can see that this relaxation is very useful for clone mode.
Others, to be supplemented.