精华内容
下载资源
问答
  • 析构函数是什么

    2012-10-10 22:10:06
    析构函数(destructor) 与构造函数相反,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。...析构函数是在类名前加~.也没有返回值. 构造函数上在对象创建时执行. 析构函数是在程序

    析构函数(destructor) 与构造函数相反,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,应在退出前在析构函数中用delete释放)。

     

    构造函数是和类同名.没有返回值.
    析构函数是在类名前加~.也没有返回值.

    构造函数上在对象创建时执行.
    析构函数是在程序结束时执行.

    一般时候析构函数里面写的都是一些资源回收之类的东西.
    不过C#的析构函数的调用机制和C++不同.并不能保证每次都会调用.所以最好不要利用C#的析构函数来回收资源.

     

    构造函数简单说是建立该函数
    析构函数就是舍弃该函数

     

    析构函数声明方式与构造函数的相同只是在类名前加个(~)符号
    析构函数不接受任何参数,不带任何反问修饰符。
    一个类只能有一个析构函数。
    析构函数不能重载
    析构函数不能显式或手动调用,只有在该类被销毁的时候调用
    由于以上特点析构函数通常用于关闭数据库,文件,网络连接等操作。

     

    c#析构函数是用于执行清除操作的特殊方法,析构函数不能重载,并且每个类只能有一个析构函数
    语法:
    ~<类名>()0
    {
    // 析构函数的主体
    }
    例:

    ~Employee()
    {

    }

     

    展开全文
  • 析构函数的作用当对象生命期结束后,收回对象占用的资源,析构函数的特点: 1、析构函数在类名前加以符号“~”。 2、析构函数没有参数、返回类型和修饰符。 3、一个类中至多有一个析构函数,如果程序员...
  • 这篇文章用于总结当析构函数是普通析构函数、虚析构函数、纯虚析构函数时,我们使用delete运算符删除一个指针对象时,析构函数会有什么情况发生; 普通析构函数 CBase是基类,CDerive是其子类,类源码代码如下: ...

    我们知道对象在结束其生命周期之前,都会调用析构函数以完成必要的清理工作;派生类调用的析构函数顺序是“先子类,后基类”; 这篇文章用于总结当析构函数是普通析构函数、虚析构函数、纯虚析构函数时,我们使用delete运算符删除一个指针对象时,析构函数会有什么情况发生;

    普通析构函数

    CBase是基类,CDerive是其子类,类源码代码如下:

    class CBase
    {
    public:
        CBase(){}
        //基类析构函数
        ~CBase(){ cout << "CBase Destructor" << endl; } 
    private:
        int a;
    };
    
    class CDerive:public CBase
    {
    public:
        CDerive(){}   
        //子类析构函数
        ~CDerive(){ cout << "CDerive Destructor" << endl; }
    private:
        int b;
    };
    

    测试代码如下:

    //case1
    CDerive *pDeriveObj = new CDerive();
    delete pDeriveObj;
    
     //case2
    //基类指针对象可以指向派生类,体现基类和派生类赋值兼容关系(不同类型可以转化和赋值),
    //但是pBaseObj只能访问基类成员,不能访问派生类成员
    CBase* pBaseObj = new CDerive();
    delete pBaseObj; //等价于删除基类对象
    

    测试结果:

    /* case 1
    先析构子类:CDerive Destructor
    后析构基类:CBase Destructor
    /
    /
    case2
    仅析构基类:CBase Destructor
    */

    总结:

    1. 若delete运算符删除的是子类指针对象,则会调用子类和基类的析构函数;
    2. 若析构函数是非虚的,即使基类指针指向的是子类对象,则delete 指针对象时,也仅调用基类的析构函数;

    虚析构函数

    当基类中的析构函数设置为虚函数时,我们在delete 基类指针对象时,能根据实际类型完成对象的清理工作;源码如下:

    class CBase
    {
    public:
        CBase(){}
        //基类虚析构函数
        virtual ~CBase(){ cout << "CBase Destructor" << endl; } 
    private:
        int a;
    };
    
    class CDerive:public CBase
    {
    public:
        CDerive(){}   
        //子类虚析构函数
        virtual ~CDerive(){ cout << "CDerive Destructor" << endl; }
    private:
        int b;
    };
    

    测试代码:

    //指向基类对象
    CBase*pBaseObj_case1 = new CBase();
    delete pBaseObj_case1;
    
    //指向子类对象
    CBase*pBaseObj_case2 = new CDerive();
    delete pBaseObj_case2;
    

    运行结果:

    //case1
    CBase Destructor
    //case2
    CDerive Destructor ->先子类
    CBase Destructor ->后基类

    总结:
    当基类的析构函数为虚函数时,基类指针指向的是子类对象时,使用delete运算符删除指针对象,析构函能够按照“先子类,后基类”的原则完成对象清理;这样在多重继承的类中,能够保证每个类都能够得到正确的清理;比如基类和子类的缓冲区都能被释放;

    纯虚析构函数

    当基类中有纯虚函数时,基类是不能被实例化的,需要在子类中重写该纯虚函数;对于纯虚析构函数有点特殊,源码如下:

    class CBase
    {
    public:
        CBase(){}
        //基类析构函数
        virtual ~CBase()= 0;
    private:
        int a;
    };
    
    class CDerive:public CBase
    {
    public:
        CDerive(){}   
        //子类析构函数
        virtual ~CDerive(){ cout << "CDerive Destructor" << endl; }
    private:
        int b;
    };
    

    测试代码:

    CBase*pBaseObj = new CDerive();
    delete pBaseObj;
    

    当我们编译代码时,会发现代码编译不过提示:
    “error LNK2019: 无法解析的外部符号 “public: virtual __thiscall CBase::~CBase(void)” (??1CBase@@UAE@XZ),该符号在函数 “public: virtual __thiscall CDerive::~CDerive(void)” (??1CDerive@@UAE@XZ) 中被引用”

    原因是子类析构时需要调用基类的析构函数,但发现代码中没有实现CBase析构函数,导致编译异常;
    解决办法就是我们在CBase类外实现其函数体,而不是在子类中重写,而且~CDerive函数也是虚函数,即使其函数名不同;这就是和其他纯虚函数有特殊的地方;

    我们需要在CBase类外增加如下的析构函数:

    CBase::~CBase()
    { 
        cout << "CBase Destructor" << endl; 
    } 
    

    这样得到的运行结果是:

    CDerive Destructor ->先子类
    CBase Destructor ->后基类

    总结
    最好把基类的析构函数声明为虚函数。这将使所有派生类的析构函数自动成为虚函数。这样,如果程序中显式地用了delete运算符准备删除一个对象,而delete运算符的操作对象用了指向派生类对象的基类指针,则系统会调用相应类的析构函数。

    专业人员一般都习惯声明虚析构函数,即使基类并不需要析构函数,也显式地定义一个函数体为空的虚析构函数,以保证在撤销动态分配空间时能得到正确的处理。

    参考资料:
    https://www.cnblogs.com/jinxiang1224/p/8468244.html
    http://c.biancheng.net/cpp/biancheng/view/247.html
    http://blog.csdn.net/yapian8/article/details/46418687

    展开全文
  • C++中基类的析构函数什么要用virtual虚析构函数

    万次阅读 多人点赞 2018-08-11 15:53:07
    大家知道,析构函数是为了在对象不被使用之后释放它的资源,虚函数是为了实现多态。那么把析构函数声明为vitual有什么作用呢?直接的讲,C++中基类采用virtual虚析构函数是为了防止内存泄漏。具体地说,如果派生类中...

    大家知道,析构函数是为了在对象不被使用之后释放它的资源,虚函数是为了实现多态。那么把析构函数声明为vitual有什么作用呢? 直接的讲,C++中基类采用virtual虚析构函数是为了防止内存泄漏。具体地说,如果派生类中申请了内存空间,并在其析构函数中对这些内存空间进行释放。假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数。那么在这种情况下,派生类中申请的空间就得不到释放从而产生内存泄漏。所以,为了防止这种情况的发生,C++中基类的析构函数应采用virtual虚析构函数。

    请看下面的代码:

    #include <iostream>
    using namespace std;
    
    class Base
    {
    public:
        Base() {}; //Base的构造函数
        ~Base() //Base的析构函数
        {
            cout << "Output from the destructor of class Base!" << endl;
        };
        virtual void DoSomething()
        {
            cout << "Do something in class Base!" << endl;
        };
    };
    
    class Derived : public Base
    {
    public:
        Derived() {}; //Derived的构造函数
        ~Derived() //Derived的析构函数
        {
            cout << "Output from the destructor of class Derived!" << endl;
        };
        void DoSomething()
        {
            cout << "Do something in class Derived!" << endl;
        };
    };
    
    int main()
    {
        Derived *pTest1 = new Derived(); //Derived类的指针
        pTest1->DoSomething();
        delete pTest1;
    
        cout << endl;
    
        Base *pTest2 = new Derived(); //Base类的指针
        pTest2->DoSomething();
        delete pTest2;
    
        return 0;
    }

    先看程序输出结果:

    可以正常释放pTest1的资源,而没有正常释放pTest2的资源,因为从结果看Derived类的析构函数并没有被调用。通常情况下类的析构函数里面都是释放内存资源,而析构函数不被调用的话就会造成内存泄漏。原因是指针pTest2是Base类型的指针,释放pTest2时只进行Base类的析构函数。在代码~Base析构函数前面加上virtual关键字后的运行结果如下:


    此时释放指针pTest2时,由于Base的析构函数是virtual的,就会先找到并执行Derived类的析构函数,然后再执行Base类的析构函数,资源正常释放,避免了内存泄漏。
    因此,只有当一个类被用来作为基类的时候,才会把析构函数写成虚函数。

    展开全文
  • C++默认的***析构函数不是虚函数是因为虚函数需要额外的虚函数表和虚表指针,占用额外的内存***。而对于不会被继承的类来说,其析构函数如果是虚函数,就会浪费内存。因此C++默认的析构函数不是虚函数,而是只有当...

    将可能会被继承的父类的析构函数设置为虚函数,可以保证当我们new一个子类,然后使用基类指针指向该子类对象,释放基类指针时可以释放掉子类的空间,防止内存泄漏。

    C++默认的***析构函数不是虚函数是因为虚函数需要额外的虚函数表和虚表指针,占用额外的内存***。而对于不会被继承的类来说,其析构函数如果是虚函数,就会浪费内存。因此C++默认的析构函数不是虚函数,而是只有当需要当作父类时,设置为虚函数。

    C++中析构函数的作用
    析构函数与构造函数对应,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统会自动执行析构函数。
    析构函数名也应与类名相同,只是在函数名前面加一个位取反符,例如stud( ),以区别于构造函数。它不能带任何参数,也没有返回值(包括void类型)。只能有一个析构函数,不能重载。

    如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数(即使自定义了析构函数,编译器也总是会为我们合成一个析构函数,并且如果自定义了析构函数,编译器在执行时会先调用自定义的析构函数再调用合成的析构函数),它也不进行任何操作。所以许多简单的类中没有用显式的析构函数。

    如果一个类中有指针,且在使用的过程中动态的申请了内存,那么最好显示构造析构函数在销毁类之前,释放掉申请的内存空间,避免内存泄漏。

    类析构顺序:1)派生类本身的析构函数;2)对象成员析构函数;3)基类析构函数。

    静态函数和虚函数的区别:
    静态函数在编译的时候就已经确定运行时机,虚函数在运行的时候动态绑定。虚函数因为用了虚函数表机制,调用的时候会增加一次内存开销

    请你说一说你理解的虚函数和多态
    多态的实现主要分为静态多态和动态多态,***静态多态主要是重载,在编译的时候就已经确定;动态多态是用虚函数机制实现的,在运行期间动态绑定。***举个例子:一个父类类型的指针指向一个子类对象时候,使用父类的指针去调用子类中重写了的父类中的虚函数的时候,会调用子类重写过后的函数,在父类中声明为加了virtual关键字的函数,在子类中重写时候不需要加virtual也是虚函数。
    虚函数的实现:在有虚函数的类中,类的最开始部分是一个虚函数表的指针,这个指针指向一个虚函数表,表中放了虚函数的地址,实际的虚函数在代码段(.text)中。当子类继承了父类的时候也会继承其虚函数表,当子类重写父类中虚函数时候,会将其继承到的虚函数表中的地址替换为重新写的函数地址。使用了虚函数,会增加访问内存开销,降低效率。

    展开全文
  • php中析构函数的作用:释放内存,当对象被销毁时析构函数就会被调用。定义析构函数的语法格式为:【__destruct()】。php使用垃圾回收机制,自动清除不再使用的对象,即使不使用unset函数,析构函数也会自动被调用...
  • 这篇文章用于总结当析构函数是普通析构函数、虚析构函数、纯虚析构函数时,我们使用delete运算符删除一个指针对象时,析构函数会有什么情况发生;普通析构函数CBase是基类,CDerive是其子类,类源码代码如下:class ...
  • C++默认的析构函数不是虚函数是因为虚函数需要额外的虚函数表和虚表指针,占用额外的内存。而对于不会被继承的类来说,其析构函数如果是虚函数,就会浪费内存。因此C++默认的析构函数不是虚函数,而是只有当需要当作...
  • C++中基类采用virtual虚析构函数是为了防止内存泄露的。 具体来说,如果派生类申请了内存空间,并在其析构函数中对该内存空间进行释放,如果基类采用的非虚析构函数,则删除基类指针指向的派生类对象时,就不会...
  • C++默认的析构函数不是虚函数是因为虚函数需要额外的虚函数表和虚表指针,占用额外的内存。而对于不会被继承的类来说,其析构函数如果是虚函数,就会浪费内存。因此C++默认的析构函数不是虚函数,而是只有当需要当作...
  • 里面的讨论基本上已经给出答案了,派生类的析构函数在执行完后,会自动执行基类的析构函数,这个编译器强制规定的,没有为什么,甚至你在析构函数里调用return都不会立即返回到调用处,而是会先按顺序把析构函数...
  • 今天我们来谈一谈面试 C++ 工程师时经常被谈到的一个问题:为什么析构函数必须是虚函数?为什么默认的析构函数不是虚函数? 首先,我们看一下百度百科对虚函数是怎么定义的: 在某基类中声明为 virtual并在一个或多个...
  • 析构函数

    热门讨论 2019-04-05 11:19:38
    1,析构函数是什么? 析构函数是在对象被销毁时自动调用的,它与构造函数不同,构造函数在对象被创建时就会自动调用,二狗系函数需要你自己去创建。 2,析构函数的作用? 析构函数往往用于清理善后,就是将对象...
  • 概念: 1. 与构造函数相对应 2. 与构造函数的作用相反 3. 析构函数的形式 ~类名( ) { … } 特点: 1. 固定的函数名称 ~类名( ) 2. 没有返回类型 3. 没有参数 4. 不可以重载 5. 一般由系统自动的调用 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,179
精华内容 1,271
关键字:

析构函数是什么