• 第六篇:为多态基类声明虚析构函数


    前言

           在很多类中,可以看到其析构函数都是声明为虚函数的。

           那么,为何要将析构函数声明为虚函数?哪些情况要将析构函数声明为虚函数?

           本文将为你解惑。

           在使用 C++ 实现多态的时候,有一点一定要清楚:当派生类对象经由基类指针被删除,而此基类的析构函数没有被声明为虚函数的话,那么析构函数只会释放基类部分的成员而无视派生类成员。

           如果不对这一点加以防范,那么很多时候,会带来内存泄露这样灾难性的后果。

    问题描述

           假设,有以下几个类,分别代表:钟,原子钟,水钟,腕表:

     1 //
     2 class TimeKeeper {
     3 public:
     4     TimeKeeper();
     5     ~TimeKeeper();
     6     //......
     7 };
     8 
     9 // 原子钟
    10 class AtomicClock : public TimeKeeper {
    11     //......
    12 };
    13 
    14 // 水钟
    15 class WaterClock : public TimeKeeper {
    16     //......
    17 };
    18 
    19 // 腕表
    20 class WristWatch : public TimeKeeper {
    21     //......
    22 };

           由于很多客户只关注一个时间的结果,对如何实现时间根本没兴趣,这时我们可以定义一个函数,它返回指针指向一个基类指针,指向新生成的派生类对象:

    1 TimerKeeper *ptk = getTimeKeeper();

           必须先说明一下,这个函数返回的指针指向对象必须是heap。

           好了,使用完这个指针,那么必须要delete掉吧,现在问题来了:对于不同的这几个派生类对象:原子钟,水钟,腕表,调用的确实相同的析构函数 - 基类析构函数。

    解决之道

           如要不同的对象执行其所属类自身的析构函数,那么相信你也自然而然想到了:使用虚析构函数来实现这种多态性。

           因此:

           对于要拿来实现多态的基类,其析构函数一定要声明为虚函数。

           也就是说,任何类只要带有虚函数,那么也几乎可以肯定其析构函数也要声明为虚函数。

           而对于不用拿来当基类的类,或者拿来当基类但是不需要实现多态的类,则不要将析构函数声明为虚函数类型。

           因为这样增加了无谓的开销,虚函数是会有一些开销的,至于开销是什么,以及相关细节,可以查阅其他 C++ 资料,本文不再累述。

    小结

           如果有某个类你希望将它声明为抽象类,但是一时又没确定设哪个成员函数为纯虚函数,那么自然而然想到可以将其析构函数声明为纯虚函数。不过在这种情况下,这个纯虚函数必须有定义,原因不解释。

  • 相关阅读:
    年末反思
    Flink运行时架构
    Phoenix 启动报错:Error: ERROR 726 (43M10): Inconsistent namespace mapping properties. Cannot initiate connection as SYSTEM:CATALOG is found but client does not have phoenix.schema.
    Clickhouse学习
    Flink简单认识
    IDEA无法pull代码到本地,Can't Update No tracked branch configured for branch master or the branch doesn't exist.
    第1章 计算机系统漫游
    简单的 Shell 脚本入门教程
    开源≠免费 常见开源协议介绍
    MySQL 视图
  • 原文地址:https://www.cnblogs.com/muchen/p/6353747.html
Copyright © 2020-2023  润新知