差点被派生类析构给坑到
程序员文章站
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.
输出结果如下:
分析:在父类实现一个虚析构函数时,不但会调用子类的析构函数,同时也会调用父类的析构函数。先后关系是先调用子类的析构函数再调用父类的析构函数。
推荐阅读