虚析构和纯虚析构

多态使用时,如果子类有对象开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码

解决方式:将父类中的析构函数改为虚析构或者春虚析构

虚析构和纯虚析构的共性:

  • 可以解决父类指针释放子类对象
  • 都需要有具体的函数实现

虚析构和纯虚析构的区别:

  • 如果是纯虚析构,该类属于抽象类,无法实例化对象

虚析构语法:

virtual ~类名(){}

纯虚析构语法:

virtual ~类名()=0;
类名::类名(){};

 常规操作:

#include<iostream>
using namespace std;
class animal
{
public:
    virtual void speak() = 0;
};


class dog : public animal
{
public:
    void speak()
    {
        cout << "小狗在说话" << endl;
    }
};


class cat : public animal
{
public:
    void speak()
    {
        cout << "小猫在说话" << endl;
    }
};
void test01()
{
    animal* it = new cat;
    it->speak();
    delete it;
}
int main()
{
    test01();
    system("pause");
}

但是如果子类对象有开辟空间到堆区时,在子类中创建指针:

 

class cat : public animal
{
public:
    void speak()
    {
        cout << *m_name<<"小猫在说话" << endl;
    }
    cat(string name) {
        m_name =new string(name);
    }
    string* m_name;
};
void test01()
{
    animal* it = new cat("tom");
    it->speak();
    delete it;
}

在父类子类对象中都打印一些字符会发现,子类的析构函数并没有调用,说明堆区并没有释放干净,这样就会造成内存泄露。

这是因为父类指针在析构时并不会调用子类的析构函数,导致子类如果有堆区对象,就会造成内存泄露。

cat类中有堆区属性,应该在该子类中将其释放,解决这个问就就需要虚析构

虚析构的语法就是在父类析构函数前加上一个virtual关键字,结果:

子类的析构函数已调用。

 以上就是利用父类指针解决子类对象时释放不干净的问题

纯虚析构

纯虚析构需要有什声明,也需要有具体 的实现;

有了纯虚析构后这个类也属于抽象类,无法实例化对象;

#include<iostream>
#include<string>
using namespace std;
class animal
{
public:
    animal()
    {
        cout << "animal构造函数已调用" << endl;
    }
    //virtual ~animal()  //虚析构    虚析构与纯虚析构只能存在一个
    //{
    //    cout << "animal析造函数已调用" << endl;
    //}
    virtual ~animal() = 0; //纯虚析构声明
    virtual void speak() = 0;
};
animal::~animal() //纯虚析构具体实现
{
    cout << "animal纯虚析构已调用" << endl;
};

class dog : public animal
{
public:
    void speak()
    {
        cout << "小狗在说话" << endl;
    }
};


class cat : public animal
{
public:
    void speak()
    {
        cout << *m_name<<"小猫在说话" << endl;
    }
    cat(string name) {
        cout << "cat构造函数已调用" << endl;
        m_name =new string(name);
    }
    ~cat()
    {
        if (m_name != NULL)
        {
            cout << "cat析构函数已调用" << endl;
            delete m_name;
            m_name = NULL;
        }
    }

    string* m_name;
};
void test01()
{
    animal* it = new cat("tom");
    it->speak();
    delete it;
}
int main()
{
    test01();
    system("pause");
}

 

posted @ 2019-08-27 19:18  一颗蘋果  阅读(2064)  评论(0编辑  收藏  举报