侧边栏壁纸
博主头像
LittleAO的学习小站 博主等级

在知识的沙漠寻找绿洲

  • 累计撰写 125 篇文章
  • 累计创建 27 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

C++知识点之 析构函数应该被定义成虚函数吗

LittleAO
2024-07-27 / 0 评论 / 0 点赞 / 15 阅读 / 0 字
温馨提示:
本文最后更新于2024-08-02,若内容或图片失效,请留言反馈。 部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

先假设这样一个场景,我们声明了一个基类的指针,却绑定了一个派生类的对象。如下面代码所示:

#include <iostream>
class Base
{
public:
    Base() {}
    ~Base() {}
    void DoSomething() { std::cout << "Base called." << std::endl; }
};

class Derived : public Base
{
public:
    Derived() {}
    ~Derived() {}
    void DoSomething() { std::cout << "Derived called." << std::endl; }
};

int main()
{
    Base* p = new Derived();
    p->DoSomething();   // Base called.
}

在我们未定义虚函数时,程序直接执行了基类的成员函数。析构函数也是如此,我们构建的派生类对象会调用基类的析构函数,可能会造成内存泄漏。如果我们把成员函数改成虚函数,则会这样:

#include <iostream>
class Base
{
public:
    Base() {}
    ~Base() {}
    virtual void DoSomething() { std::cout << "Base called." << std::endl; }
};

class Derived : public Base
{
public:
    Derived() {}
    ~Derived() {}
    void DoSomething() override { std::cout << "Derived called." << std::endl; }
};

int main()
{
    Base* p = new Derived();
    p->DoSomething();   // Derived called.
}

对象通过查询虚函数表,正确的调用了自己的成员函数。析构函数也会不会这样呢,再做个实验:

#include <iostream>
class Base
{
public:
    Base() {}
    ~Base() { std::cout << "Base deleted." << std::endl; }
};

class Derived : public Base
{
public:
    Derived() {}
    ~Derived() { std::cout << "Derived deleted." << std::endl; }
};

int main()
{
    Base* p = new Derived();
    delete p;   // Base called.
}

发现真的只是调用了基类的析构函数,将析构函数换成虚函数:

#include <iostream>
class Base
{
public:
    Base() {}
    virtual ~Base() { std::cout << "Base deleted." << std::endl; }
};

class Derived : public Base
{
public:
    Derived() {}
    ~Derived() override { std::cout << "Derived deleted." << std::endl; }
};

int main()
{
    Base* p = new Derived();
    delete p;   // Derived deleted.
                // Base deleted.
}

发现两个析构函数都被成功的调用了,实际上是正确找到了派生类的析构函数,派生类析构函数执行完毕后会再执行基类的析构函数。

因此我们得出结论:在多态中,析构函数最好定义为虚函数

0

评论区