Virtual destructor and pure virtual destructor in C + +

Source: Internet
Author: User
Tags define abstract

Can a destructor be a pure virtual function in C + +?

It is well known that in the process of implementing polymorphism, the destructor of the base class is generally set virtual so that it delete can be called in a multi- state chain . Then can the destructor be set to pure virtual?

class CBase{    public:        CBase()       {            printf("CBase()\n");       }    virtual0// 析构函数是纯虚函数};

The answer is yes, so what is the purpose of this implementation? Avoid instantiation , of course.

However, because a derived class cannot implement a destructor for a base class , the base class destructor can be marked as pure virtual, but the destructor must still be implemented, otherwise the derived class cannot inherit or compile through .

Discussed in detail below:

Virtual destructor

We know that in order to be able to correctly invoke the destructor of an object, it is generally required that a top-level class with a hierarchy define its destructor as a virtual function. Because in delete an abstract class pointer, you have to find the real destructor through the virtual function.

Such as:

class Base  {      public:          Base(){}          virtual ~Base(){}  };  public Base  {      public:          Derived(){};          ~Derived(){};  }  void foo()  {     Base *pb;     new Derived;     delete pb;  

This is the correct usage that will occur when dynamic binding , which will call Derived the destructor first, and then Base the destructor

If the destructor is not added virtual , delete pb only Base the destructor is executed, not the actual Derived destructor.

Because it is not virtual a function, the function that is called depends on pointing to the static type , that is Base .

Pure virtual destructor

The problem now is that we want to Base make an abstract class that cannot directly construct an object and need to define a pure virtual function in it. If there are no other suitable functions, the destructor can be defined as pure virtual, and the preceding definition will be CObject changed to:

class Base  {      public:          Base(){}          virtual0;  

However, this code cannot be compiled, usually an link error, and cannot be found ~Base() by the reference ( gcc error report).

error"public: virtual __thiscall Base::~Base(void)" (??1Base@@UAE@XZin"public: virtual __thiscall Derived::~Derived(void)" (??1Derived@@UAE@XZ)1error1 unresolved externals

This is because destructors, constructors, and other intrinsic functions are different, and when called, the compiler needs to produce a call chain . That is, the destructor that is Derived implicitly called Base in destructors. The missing function body in the code just now ~Base() will, of course, be wrong.

There is a misunderstanding, some people think that virtual f()=0 this pure virtual function syntax is not defined by the semantics of the body.

In fact, this is not right. This syntax simply indicates that the function is a pure virtual function , so this class becomes an abstract class and cannot produce an object . We can definitely specify the function body for pure virtual functions. The usual pure virtual function does not require the function body, because we generally do not invoke this function of the abstract class, only the corresponding function of the derived class is called. Thus, we have a pure virtual destructor function body, the above code needs to be changed to:

class Base  {      public:          Base(){}          virtual0//pure virtual  };  Base::~Base()//function body  {  }  

From a syntactic point of view, the above destructors cannot be written directly to the class declaration (the method of inline functions). This may be a non-orthogonal place. But it does seem a little cumbersome.

This problem seems to be somewhat scholarly, because generally we can Base find a more suitable function in, by defining it as a pure virtual function without an implementation body, and defining an entire class as an abstract class. But this technique also has some applications, such as this example:

classBase//abstract class{ Public:Virtual~base () {};//virtual, not pure        Virtual voidHiberarchy ()Const=0;//pure Virtual};voidBase::hiberarchy ()Const //pure Virtual also can has function body{STD::cout<<"Base::hiberarchy"; }classDerived: PublicBase { Public: Derived () {}Virtual voidHiberarchy ()Const{Base::hiberarchy ();STD::cout<<"Derived::hiberarchy"; }Virtual voidFoo () {}};intMain () {base* pb=NewDerived ();     Pb->hiberarchy (); Pb->base::hiberarchy ();return 0; }

In this example, we try to print out the inheritance relationship of the class. Virtual functions are defined in the base class Hiberarchy and are then overloaded in each derived class. Once again we see that because we want to make Base an abstract class, and no other suitable method member in this class can be defined as pure virtual, we still have to Hiberarchy define it as pure virtual. (Of course, the function can be defined entirely ~Base , as discussed above.) ^_^)

In addition, you can see that main there are two methods of invocation, the first is the normal way, dynamic link, execute virtual function, get the result, the "Derived::Hiberarchy" second is to specify the way of the class, no longer perform the virtual function dynamic link process, the result is "Base::Hiberarchy" .

As you can see from the above analysis, the real purpose of defining pure virtual functions is to define abstract classes , not the function itself. In contrast, in java , the syntax for defining abstract classes is abstract class to specify at the class level (of course, the virtual function or the abstract keyword). Isn't this the better way? In the Stroustrup design and evolution of the C + + language, I found this passage:

"I chose to describe individual functions as pure virtual, not in the form of defining a complete class declaration as abstract, because the concept of pure virtual functions is more flexible. I value the ability to define classes in stages, that is to say, I find it useful to define some pure virtual functions in advance, and to define other classes for further derivation. "

I have not fully understood the latter sentence, and I would like to elaborate on this concept from another perspective. That is, in a multi-layered complex class structure, the intermediate-level classes should materialize some abstract functions, but probably not all of them. The middle class does not need to know whether to materialize all the virtual functions, and what functions their ancestors have materialized, as long as they focus on their duties . In other words, the middle class does not need to know whether it is a real abstract class, and the designer does not have to consider whether or not to add a similar description at the class level of the intermediate class abstract .

Of course, the design of a language has a variety of factors, good or bad are all aspects. It's just an explanation.

Finally, some common questions about virtual functions are summarized:
    1. virtual functions are dynamically bound , that is, pointers and references that use virtual functions can correctly locate the corresponding function of the actual class, rather than executing the function that defines the class. This is the basic function of the virtual function, it is no longer explained.

    2. A constructor cannot be a virtual function . Furthermore, the virtual function is called in the constructor, and the corresponding function of the parent class is actually executed, because the polymorphism is not well constructed disable .

    3. Destructors can be virtual functions, and in a complex class structure, this is often necessary .

    4. defining a function as a pure virtual function is actually defining the class as an abstract class and cannot instantiate an object .

    5. a pure virtual function usually has no body defined, but it can be owned and even displayed.

    6. Destructors can be purely virtual, but pure virtual destructors must have a defined body, because the invocation of the destructor is implicit in the subclass .

    7. A non-pure virtual function must have a defined body, or it is an error.

    8. The virtual function definition of a derived class override must be exactly the same as the parent class ( c++11 used in the override compiler Check). In addition to a special case, if the return value in the parent class is a pointer or reference, the child class override can return the derivation of the pointer (or reference). For example, in the example above, defined in, Base virtual Base* clone() Derived can be defined as in virtual Derived* clone() . As you can see, this relaxation Clone is very useful for patterns (that is, it override does not check the return value type).

Virtual destructor and pure virtual destructor in C + +

Related Article

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.