虚析构函数

虚析构函数

#include <iostream>
#include<string>
#include<cstdlib>

using namespace std;

class A
{
public:
    ~A()
    {
        cout << "A destructor" << endl;
    }
};
class B :public A
{
    ~B()
    {
        cout << "B destructor" << endl;
    }
};

int main()
{
    A *pa = new B;
    delete pa;
    return 0;
}

运行结果:

A destructor    // 只引发了 A 类的析构函数被调用,没有引发 B 类的析构函数

当将基类指针指向 new 运算符动态生成的派生类对象时,要通过 delete 来释放,应为该语句是静态联编的,编译器不可能知道此时 pa 指向哪个类型的对象,它只是根据 pa 类型是 A * ,来决定调用 A 类的析构函数,但实际上应该调用 B 类的析构函数才符合逻辑。

综上,delete pa 这样的语句应该根据 pa 所指的对象,来执行相应的析构函数。要实现这点,也用到了多态。因此,需要将基类的析构函数声明为虚函数,即虚析构函数。

改为:

class A
{
    virtual ~A()
    {
        cout << "A destructor" << endl;
    }
}
运行结果:

B destructor
A destructor

注意

  1. 派生类的析构函数会自动调用基类的析构函数。

  2. 一般,如果一个类定义了虚函数,则最好将析构函数也定义成虚函数。

  3. 只要在基类中某个函数被声明为虚函数,那么在派生类中,同名,同参数表的成员函数即使前面不写 virtual 关键字,也自动成为虚函数。

  4. 编译器看到是哪个类的指针,那么就会认为通过它访问的,就应该是哪个类的成员,编译器不会分析基类指针到底指向的是基类对象还是派生类对象。

#include <iostream>

using namespace std;

class A
{
public:
    void fun()
    {
        cout << "A called" << endl;
    }
};
class B :public A
{
    void fun()
    {
        cout << "B called" << endl;
    }
};
int main(void)
{
    B b;
    A *pa = &b;
    pa->fun();

    return 0;
}
运行结果:

A called

如果用上多态,则解决了这个问题:

#include <iostream>

using namespace std;

class A
{
public:
    virtual void fun()
    {
        cout << "A called" << endl;
    }
};
class B :public A
{
    void fun()
    {
        cout << "B called" << endl;
    }
};
int main(void)
{
    B b;
    A *pa = &b;
    pa->fun();

    return 0;
}
运行结果:

B called

由上,只在基类 A 中的 fun 函数前加了关键字 virtual (line 120),是该函数及其派生类中的同名,同参数表中的成员函数自动成为了虚函数,通过基类的指针调用虚函数时,就用到了多态。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 2-7虚函数与虚析构函数实现原理 [TOC] 1.虚函数的实现原理 (1)引入概念:函数指针。 ​ 指向函数的...
    青_阳阅读 630评论 0 1
  • 为什么构造函数不能声明虚函数 在C++中,构造函数用于在创建对象时进行初始化工作,不能声明为虚函数。因为在执行构造...
    tomchan阅读 278评论 0 1
  • 通过学习我们了解到派生类对象是由积累部分和派生类不恨构成的,那么该派生类对象是如何被析构和够早的呢? #inclu...
    舌尖上的搬砖汉阅读 362评论 0 1
  • 基类的析构函数一般都会被声明成虚函数,原因是,若是不设置成虚函数,在实现多态时,将子类对象赋给基类指针,在析构的过...
    Roling阅读 2,070评论 1 3
  • 为什么要使用虚析构函数 举例 打印: Son 存在的问题实际上创建的是一个派生类的对象,但是调用的却是基类的析构函...
    Mitchell阅读 1,073评论 0 0