• 为什么析构函数是虚函数比较好?


    原因:基类对象的指针操作派生类对象时,防止析构函数只调用基类的,而不调用派生类的

    下面详细说明:

    //基类
     
    class A{
       public :
           A(){ cout<<"A构造函数"<<endl; }
           ~A(){cout<<"A被销毁了"<<endl;}
           void Do(){
               cout<<"A要做点什么"<<endl;
           }
    };
    //派生类
     
    class B :public A{
        public :
            B(){ cout<<"B构造函数"<<endl;}
            ~B(){ cout<<"B被销毁了"<<endl;}
            void Do(){ cout<<"B要做点什么"<<endl;}
    };

    (1)派生类 指针=new 派生类;

             B      *p   =new B;      那么就会执行基类构造函数,派生类构造函数

             p->Do();   通过派生类指针可以调用派生类的成员函数

             delete p;     先调用派生类析构函数,在调用基类构造函数

             

    #include<iostream>
    using namespace std;
    //基类
     
    class A{
       public :
           A(){ cout<<"A构造函数"<<endl; }
           ~A(){cout<<"A被销毁了"<<endl;}
           void Do(){
               cout<<"A要做点什么"<<endl;
           }
           
    };
    //派生类
     
    class B :public A{
        public :
            B(){ cout<<"B构造函数"<<endl;}
            ~B(){ cout<<"B被销毁了"<<endl;}
            void Do(){ cout<<"B要做点什么"<<endl;}
    };
    int main(){
        B *p=new B;
        p->Do();
        delete p;
        return 0;
    }
    派生类指针操作派生类成员函数

    (2)派生类 指针=new 基类;  会出错,基类指针不能转换成派生类指针

    (3)基类 指针 = new 派生类;  (派生类指针转化成基类指针)

           A    *p    = new B;     依旧要先调用基类构造函数,再派生类构造函数

           p ->Do();    通过基类指针调用基类成员函数,此处只能调用基类里面有的成员函数,当调用派生类中成员函数会提示基类中并没有这个成员

           delete p;      这里只会调用基类的析构函数,所以内存释放并不完全

    #include<iostream>
    using namespace std;
    //基类
     
    class A{
       public :
           A(){ cout<<"A构造函数"<<endl; }
           ~A(){cout<<"A被销毁了"<<endl;}
           void Do(){
               cout<<"A要做点什么"<<endl;
           }
           
    };
    //派生类
     
    class B :public A{
        public :
            B(){ cout<<"B构造函数"<<endl;}
            ~B(){ cout<<"B被销毁了"<<endl;}
            void Do(){ cout<<"B要做点什么"<<endl;}
    };
    int main(){
        A *p=new B;
        p->Do();
        delete p;
        return 0;
    }
    派生类指针转换成基类指针

       

    (4)上面(3)知道了这样影响了内存的释放完整程度,所以我们通过引入虚函数机制,将基类的析构函数定义成虚函数

    //基类
     
    class A{
       public :
           A(){ cout<<"A构造函数"<<endl; }
           virtual ~A(){cout<<"A被销毁了"<<endl;}
           void Do(){
               cout<<"A要做点什么"<<endl;
           }
    };
    //派生类
     
    class B :public A{
        public :
            B(){ cout<<"B构造函数"<<endl;}
            ~B(){ cout<<"B被销毁了"<<endl;}
            void Do(){ cout<<"B要做点什么"<<endl;}
    };

    然后 delete p;就会释放派生类,释放基类

    #include<iostream>
    using namespace std;
    //基类
     
    class A{
       public :
           A(){ cout<<"A构造函数"<<endl; }
           virtual ~A(){cout<<"A被销毁了"<<endl;}
           void Do(){
               cout<<"A要做点什么"<<endl;
           }
           
    };
    //派生类
     
    class B :public A{
        public :
            B(){ cout<<"B构造函数"<<endl;}
            ~B(){ cout<<"B被销毁了"<<endl;}
            void Do(){ cout<<"B要做点什么"<<endl;}
    };
    int main(){
        A *p=new B;
        p->Do();
        delete p;
        getchar();
        return 0;
    }
    析构函数变成了虚函数,发现可以正常释放内存

    总结:引入虚函数后,因为基类对象的指针可以指向派生类的对象(多态性),所以如果删除指针delete p,那么就会调用派生类得析构函数,但是派生类的析构函数就会调用基类的析构函数,这样整个派生类的对象完全被释放。但是如果不被声明成虚函数,那么删除指针时,只会调用基类的析构函数,而不会调用派生类的析构函数,这样释放对象就只释放不完全,所以把析构函数定义成虚函数是十分必要的。

    还有派生类指针转换成基类指针的时候,调用同名成员函数的时候,一定要调用基类的成员函数,因为此时基类的成员函数覆盖了派生类的同名成员函数。这时也需要引入虚函数来实现多态,就可以调用派生类的成员函数了

  • 相关阅读:
    paip.调用GUI接口.
    paip.按键替换映射总结
    paip.IIS 7.5 应用程序池,应用程序以及虚拟目录的存储位置
    paip.android 手机输入法制造大法
    paip.设置鼠标灵敏度API
    paip.系统无法在消息文件中为 Application 找到消息号为 0x2350 的消息文本。服务器存储空间不足,无法处理此命令
    paip.DEVSUIT WEB .NET ASPX网站打开慢的原因
    paip.动画透明淡入淡出窗口之重绘性能
    PAIP。JS调用DLL的解决方案
    paip.输入法编程四级非常用汉字汉字1000个
  • 原文地址:https://www.cnblogs.com/jijiji/p/4854363.html
Copyright © 2020-2023  润新知