zoukankan      html  css  js  c++  java
  • 为什么析构函数常声明为虚函数

    析构函数的作用与构造函数正好相反,是在对象的生命期结束时,释放系统为对象所分配的空间,即要撤消一个对象。

    用对象指针来调用一个函数,有以下两种情况:

    1. 如果是虚函数,会调用派生类中的版本。(在有派生类的情况下)

    2. 如果是非虚函数,会调用指针所指类型的实现版本。

    析构函数也会遵循以上两种情况,因为析构函数也是函数嘛,不要把它看得太特殊。 当对象出了作用域或是我们删除对象指针,析构函数就会被调用。

    当派生类对象出了作用域,派生类的析构函数会先调用,然后再调用它父类的析构函数, 这样能保证分配给对象的内存得到正确释放。

    但是,如果我们删除一个指向派生类对象的基类指针,而基类析构函数又是非虚的话, 那么就会先调用基类的析构函数(上面第2种情况),派生类的析构函数得不到调用。

    请看例子:

    #include<stdio.h>
    #include<iostream>
    class A{
    public:A();
           virtual~A();
           virtual void fun1(){
               printf("123");
           }
    };
    A::A(){}
    A::~A(){
        printf("Delete class A
    ");
    }
    
    class B : public A
    {
    public:B();
           ~B();
           void fun2(){
               printf("123456");
           }
    };
    
    B::B(){ }
    B::~B(){
        printf("Delete class B
    ");
    }    
    
    A *a=new B;
    //B *b=new A; //无法从“A *”转换为“B *”
    
    B *c=new B;
    A *d=new A;
    int main(){
    
    
        delete a;
        //delete c;
        //delete d;
        return 0;
    }
    View Code

    析构函数加上虚函数,当你动态申请一个对象时,并且把这个对象的指针赋值给基类,这时当你用这个基类指针释放内存时,就有用了,因为这样可以用多态性原理调用对象实际的析构函数来析构内存。

    #include<stdio.h>
    #include<iostream>
    class A{
    public:A();
           ~A();
           virtual void fun1(){
               printf("123");
           }
    };
    A::A(){}
    A::~A(){
        printf("Delete class A
    ");
    }
    
    class B : public A
    {
    public:B();
           ~B();
           void fun2(){
               printf("123456");
           }
    };
    
    B::B(){ }
    B::~B(){
        printf("Delete class B
    ");
    }    
    
    A *a=new B;
    //B *b=new A; //无法从“A *”转换为“B *”
    
    B *c=new B;
    A *d=new A;
    int main(){
    
    
        delete a;
        //delete c;
        //delete d;
        return 0;
    }
    View Code

    析构函数去掉虚函数,就不能调用子类中的析构函数了

    当你动态申请一个对象时,并且把这个对象的指针赋值给当前类,析构函数去掉虚函数,都不会影响子类到父类的虚构

    #include<stdio.h>
    #include<iostream>
    class A{
    public:A();
           ~A();
           virtual void fun1(){
               printf("123");
           }
    };
    A::A(){}
    A::~A(){
        printf("Delete class A
    ");
    }
    
    class B : public A
    {
    public:B();
           ~B();
           void fun2(){
               printf("123456");
           }
    };
    
    B::B(){ }
    B::~B(){
        printf("Delete class B
    ");
    }    
    
    A *a=new B;
    //B *b=new A; //无法从“A *”转换为“B *”
    
    B *c=new B;
    A *d=new A;
    int main(){
    
    
        delete c;
        //delete c;
        //delete d;
        return 0;
    }
    View Code
  • 相关阅读:
    网站制作常用的cms系统有哪些?
    企业网站建设中CMS系统的作用及现状
    PageAdmin企业网站制作中踩过的坑
    怎样制作网站的流程和步骤
    PageAdmin CMS建站系统可视化区块的使用教程
    PageAdmin CMS建站系统的可视化编辑体验
    企业网站建设常用CMS建站系统推荐
    PageAdmin CMS内容管理系统v4.0.11体验评测
    文本框检测回车按键或条码扫描结束回车符
    主播说联播 :铭记历史是为了创造历史 这三样东西不能丢!
  • 原文地址:https://www.cnblogs.com/huhuuu/p/3453063.html
Copyright © 2011-2022 走看看