【Qt】【C++】虚析构函数及 virtual ~Base() = default

1. 虚析构函数的作用

虚析构函数的主要作用是避免内存泄漏。当基类指针指向子类对象时,如果基类的析构函数不是虚函数,那么在删除基类指针时,只会调用基类的析构函数,而不会调用子类的析构函数。这会导致子类的资源没有被正确释放,从而造成内存泄漏。

2. 代码

  • Test.cpp
cpp 复制代码
#ifndef TEST_H
#define TEST_H

#include <qdebug.h>

//虚析构函数
class Base1
{
public:
    virtual ~Base1() { qDebug() << "Base1 del"; }
    virtual void show() { qDebug() << "Base1 show"; }
};

class Derived1 : public Base1
{
public:
    ~Derived1() { qDebug() << "Derived1 del"; }
    virtual void show() override { qDebug() << "Derived1 show"; }
};

//普通析构函数
class Base2
{
public:
    ~Base2() { qDebug() << "Base2 del"; }
    virtual void show() { qDebug() << "Base2 show"; }
};

class Derived2 : public Base2
{
public:
    ~Derived2() { qDebug() << "Derived2 del"; }
    virtual void show() override { qDebug() << "Derived2 show"; }
};

#endif // TEST_H
  • main.cpp
cpp 复制代码
#include "Test.h"

int main(int argc, char *argv[])
{
    Base1* test1 = new Derived1;
    test1->show();
    delete test1;

    qDebug() << "";

    Base2* test2 = new Derived2;
    test2->show();
    delete test2;

    return 0;
}
  • 结果
cpp 复制代码
Derived1 show
Derived1 del
Base1 del

Derived2 show
Base2 del
  • 结论
    • 虚析构函数的例子中,调用了子类的析构函数
    • 正常析构函数的例子中,没有调用子类的析构函数

3. virtual ~Base() = default的作用

在 C++11 中,virtual ~base() = default 是一种显式声明默认析构函数的方式。它的主要作用是让编译器生成默认的析构函数,同时保留其虚函数的特性。这种用法在现代 C++ 编程中非常重要,尤其是在涉及继承和多态的场景中。

  • 保留虚函数特性:当基类的析构函数被声明为虚函数时,派生类的析构函数会被正确调用。这对于通过基类指针删除派生类对象至关重要。如果基类的析构函数不是虚函数,可能会导致资源泄漏。

  • 显式默认行为 :使用 = default 明确表示析构函数的行为是由编译器生成的,而不是用户自定义的。这种方式可以提高代码的可读性和维护性。

  • 支持隐式移动操作 :如果析构函数被用户定义(即使是空实现),编译器将不会生成隐式的移动构造函数和移动赋值运算符。而使用 = default 可以避免这一问题,保留隐式的移动操作。

4. virtual ~Base() = default 与 virtual ~base() {} 的区别

  • 性能优化= default 让编译器生成的析构函数更高效,因为它直接调用编译器内部的实现,而不是用户定义的空函数。

  • 隐式移动支持 :如果使用 virtual ~base() {},编译器会认为析构函数是用户定义的,从而禁用隐式的移动构造函数和移动赋值运算符。而 = default 不会影响这些操作。

  • 代码意图清晰= default 明确表达了程序员希望使用编译器生成的默认行为,而不是自定义逻辑。

5. 代码模板

cpp 复制代码
#ifndef TEST_H
#define TEST_H

//虚析构函数
class Base
{
public:
    virtual ~Base() = default;
    virtual void show();
};


#endif // TEST_H
相关推荐
charlie1145141918 分钟前
精读C++20设计模式——行为型设计模式:迭代器模式
c++·学习·设计模式·迭代器模式·c++20
Le1Yu24 分钟前
2025-9-28学习笔记
java·笔记·学习
小欣加油25 分钟前
leetcode 1863 找出所有子集的异或总和再求和
c++·算法·leetcode·职场和发展·深度优先
C++chaofan29 分钟前
项目中为AI添加对话记忆
java·数据结构·人工智能·redis·缓存·个人开发·caffeine
老华带你飞29 分钟前
机电公司管理小程序|基于微信小程序的机电公司管理小程序设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·微信小程序·小程序·机电公司管理小程序
拾忆,想起1 小时前
AMQP协议深度解析:消息队列背后的通信魔法
java·开发语言·spring boot·后端·spring cloud
PH = 71 小时前
Spring Ai Alibaba开发指南
java·后端·spring
00后程序员张2 小时前
从零构建 gRPC 跨语言通信:C++ 服务端与
开发语言·c++
涛声依旧2 小时前
基于springBoot鲜花商城小程序
java·spring·微信小程序
爱凤的小光3 小时前
图漾相机C++语言---Sample_V1(4.X.X版本)完整参考例子(待完善)
开发语言·c++·数码相机