欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

差点被派生类析构给坑到

程序员文章站 2023-12-31 22:16:04
...

关键字:纯虚函数、纯虚析构函数、派生类


由于基础不够扎实,今天在写代码时发现一个底层的小坑,在delete子类的时候只会调用父类的析构函数不会调用子类的析构函数。

这样可能导致的重大问题是,在析构子类对象时可能子类内部对象并未被释放,造成内存泄露。

具体情况上代码分析。

问题代码如下

声明:

/****************************************************************
 Doc    :   State.h
 Author :   BingLee
 Date   :   2020-08-17
 Info   :   State Design Patten
 https://blog.csdn.net/Bing_Lee (C)All rights reserved.
******************************************************************/
#include <QString>

class DrawState
{
public:
    //=======================父类析构函数分为如下三种情况=========================
    							//1. no destructor.
    //~DrawState();				//2.default destructor.
    //virtual ~DrawState();		//3.virtual destructor.
    virtual void paint(QString &str) = 0;
};

class DrawRed : public DrawState
{
public:
    DrawRed();
    ~DrawRed();
    virtual void paint(QString &str);
};

class DrawYellow : public DrawState
{
public:
    DrawYellow();
    ~DrawYellow();
    virtual void paint(QString &str);
};

class DrawBlue : public DrawState
{
public:
    DrawBlue();
    ~DrawBlue();
    virtual void paint(QString &str);
};

实现:

#include "state.h"
#include <stdio.h>

=======================父类析构函数实现分为如下三种情况=========================
=================1. no destructor.
//
=================2.default destructor.
//DrawState::~DrawState()
//{
//    printf("~DrawState()\n");
//}
=================3.virtual destructor.
//DrawState::~DrawState()
//{
//    printf("~DrawState()\n");
//}

DrawRed::DrawRed()
{
}

DrawRed::~DrawRed()
{
    printf("~DrawRed()\n");
}

void DrawRed::paint(QString &str)
{
    printf("Draw %s in Red.\n", str.toStdString().c_str());
}

DrawYellow::DrawYellow()
{
}

DrawYellow::~DrawYellow()
{
    printf("~DrawYellow()\n");
}

void DrawYellow::paint(QString &str)
{
    printf("Draw %s in Yellow.\n", str.toStdString().c_str());
}

DrawBlue::DrawBlue()
{
}

DrawBlue::~DrawBlue()
{
    printf("~DrawBlue()\n");
}

void DrawBlue::paint(QString &str)
{
    printf("Draw %s in Blue.\n", str.toStdString().c_str());
}

用户:

/****************************************************************
 Doc    :   main.cpp
 Author :   BingLee
 Date   :   2020-08-17
 Info   :   State Design Patten
 https://blog.csdn.net/Bing_Lee (C)All rights reserved.
******************************************************************/
#include <QCoreApplication>
#include "state.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    
    QString drawObj = "Circle";
    DrawState *drawRed = new DrawRed();
    DrawState *drawYellow = new DrawYellow();
    DrawState *drawBlue = new DrawBlue();

    drawRed->paint(drawObj);
    drawYellow->paint(drawObj);
    drawBlue->paint(drawObj);

    delete drawRed;
    delete drawYellow;
    delete drawBlue;

    return a.exec();
}

运行结果

第一种情况

第一种情况,父类并没有写析构函数//1. no destructor.

输出结果如下:

差点被派生类析构给坑到

分析:不会调用派生类的析构函数,也不会调用父类的析构函数,应该父类在未声明析构函数时会默认添加一个析构函数。

第二种情况

第二种情况,父类写一个默认的析构函数//2.default destructor.

输出结果如下:

差点被派生类析构给坑到

分析:均会调用父类的析构函数,但是不会调用子类的析构函数。

第三种情况

第三种情况,父类实现虚析构函数//3.virtual destructor.

输出结果如下:

差点被派生类析构给坑到

分析:在父类实现一个虚析构函数时,不但会调用子类的析构函数,同时也会调用父类的析构函数。先后关系是先调用子类的析构函数再调用父类的析构函数。

上一篇:

下一篇: