类的四个默认成员函数->析构函数

3.析构函数

1.析构函数的概念

  析构函数可以理解为反向的构造函数,他在对象生命期结束时,调用析构函数释放对象的内存空间。具体的析构函数在这几种情况下调用:

  1.堆上的空间(使用new创建的对象)调用delete时

  2.本地对象超出作用域

  3.临时对象的销毁

  4.显式的调用析构函数

2.析构函数注意事项

  1.析构函数没有参数

  2.析构函数不能重载

  3.析构函数没有返回类型。

3.虚析构函数

  虚析构函数是析构函数的重点,在出现继承时,构造函数不用考虑因为继承产生的问题,因为派生类的构造函数会自动调用基类的构造函数,析构函数与构造函数类似,派生类的析构函数也会自动调用。但是在继承体系中会出现一些问题。考虑这种情况。

class A
{
public:
    A(int _a=15):a(_a){}
    ~A()
    {
        cout << "~A()" << endl;
    }
private:
    int a;
};
class B :public A
{
public:
    B(int _a=15,int _b=10) : A(_a),b(_b){}
    ~B()
    {
        cout << "~B()" << endl;
    }
private:
    int b;
};
int main()
{
    A *k = new B(11,22);
    delete k;
    return 0;
}

测试结果:~A()

  使用基类的指针指向派生类的对象时,调用delete k,会调用A的析构函数去释放内存,k虽然指向一个派生类的对象,但是k指针的类型是基类的,所以析构函数只能释放掉派生类中的基类部分,派生类自己特有的部分并没有被释放掉。这时,产生了内存泄漏。

  这时我们引入虚函数这个概念。指向基类的指针在操作它的多态对象的虚函数时,会根据不同的对象操作对象自身的函数,当析构函数为虚函数时,编译器在执行析构函数时,会根据指针所指对象来决定调用那个函数,而不是根据指针类型来决定。

class A
{
public:
    A(int _a=15):a(_a){}
    virtual ~A()
    {
        cout << "~A()" << endl;
    }
private:
    int a;
};
class B :public A
{
public:
    B(int _a=15,int _b=10) : A(_a),b(_b){}
    ~B()
    {
        cout << "~B()" << endl;
    }
private:
    int b;
};
int main()
{
    A *k = new B(11,22);
    delete k;
    return 0;
}

测试结果:

~B()

~A()

执行派生类的析构函数。(打印两行是因为派生类的析构函数会自动调用基类的析构函数)。

 

posted @ 2017-03-17 19:31  是召不是昭  阅读(1127)  评论(0编辑  收藏  举报