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

前言

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

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

本文将为你解惑。

在使用 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++ 资料,本文不再累述。

小结

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

时间: 2024-11-03 03:47:41

第六篇:为多态基类声明虚析构函数的相关文章

EC笔记,第二部分:7.为多态基类声明虚析构函数

7.为多态基类声明虚析构函数 1.为多态基类声明虚析构函数 code1: class A{ public: int* a; A():a(new int(5)) {} ~A(){ delete a; } }; class B:public A { public: int *b; B():b(new int(10)) {} ~B(){ delete b; } }; int main(int argc, char const *argv[]) { B *bb=new B; A* aa=bb; dele

为多态基类声明虚析构函数

前言 在使用 C++ 实现多态的时候,有一点一定要清楚:当派生类对象经由基类指针被删除,而此基类的析构函数没有被声明为虚函数的话,那么析构函数只会释放基类部分的成员而无视派生类成员. 如果不对这一点加以防范,那么很多时候,会带来内存泄露这样灾难性的后果. 解决之道 1. 对于要拿来实现多态的基类,其析构函数一定要声明为虚函数. 也就是说,任何类只要带有虚函数,那么也几乎可以肯定其析构函数也要声明为虚函数. 2. 对于不用拿来当基类的类,或者拿来当基类但是不需要实现多态的类,则不要将析构函数声明为

Effective C++_笔记_条款07_为多态基类声明virtual析构函数

(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 这个规则只适用于polymorphic(带多态性质的)base class身上.这种base class的设计目的是为了用来“通过base class接口处理derived class对象”.假如我们在程序中设计factory(工厂)函数,让它返回base class指针,指向新生成的derived class对象,假设base class有个non-virtu

Effective C++ Item 07-为多态基类声明virtual析构函数

Item 07-为多态基类声明virtual析构函数 Declare destructors virtual in polymorphic base class why?  http://blog.csdn.net/wxqian25/article/details/7361069 Ex: 记录时间有多种做法,一个基类和一些派生类 class TimeKeeper{                        //    base class 基类 public: TimeKeeper(); ~

Effective C++ 条款七 为多态基类声明virtual析构函数

class TimeKeeper { public: TimeKeeper(); // ~TimeKeeper(); 错误,此作为一个基类,被继承了.其继承类被delete后,基类被销毁,但继承类可能没被销毁 virtual ~TimeKeeper();//必须声明为virtual类型才可以. protected: private: };   class AtomicClock: public TimeKeeper{}; //继承   TimeKeeper* ptk = getTimeKeepe

条款7:为多态的基类声明虚析构函数。

任何的类只要带有一个virtual函数那么就集合可以确定其应该有一个virtual析构函数. 同样的如果一个函数不含有virtual函数,那么通常意味着其不是一个基类函数,而且为一个不是基类的类声明virtual的析构函数是十分糟糕的事情,不要这样做.具体原因在下面: 1.首先,想要实现出virtual函数,对象必须要携带某些信息,.信息通过vptr来实现,这个vptr指向一个由函数指针构成的数组,即vtbl.盲目的去使用虚函数就会使得浪费资源.(一般人的经验是,只有当函数需要使用一个虚函数的时

条款7:为多态基类声明virtual析构函数

C++明确指出:当派生类对象是由一个基类指针释放的,而基类中的析构函数不是虚函数,那么结果是未定义的.其实我们执行时其结果就是:只调用最上层基类的析构函数,派生类及其中间基类的析构函数得不到调用. 1 #include <iostream> 2 3 using namespace std; 4 5 class TimeKeeper 6 { 7 public: 8 TimeKeeper(); 9 ~TimeKeeper(); 10 }; 11 TimeKeeper::TimeKeeper() 1

Effective C++学习笔记 条款07:为多态基类声明virtual析构函数

一.C++明确指出:当derived class对象经由一个base class指针被删除,而该base class带着一个non-virtual析构函数,其结果未定义——实际执行时通常发生的是对象的derived成分没有被销毁!(注:使用基类引用派生类的方式使用多态,由于引用只是对原对象的一个引用或者叫做别名,其并没有分配内存,对其引用对象内存的销毁,将由原对象自己负责,所以使用引用的时候,如果析构函数不为virtual,那么也不会发生derived成员没有销毁的情况) 例如: class b

effective c++ 条款07(为多态基类声明virtual析构函数)整理

一.虚函数表原理 陈皓的一篇blog讲的很透彻:http://blog.csdn.net/haoel/article/details/1948051/ 虚函数表可以分为:单一继承无虚函数覆盖.单一继承有虚函数覆盖.多重继承无虚函数覆盖和多重继承和有虚函数覆盖. 注意与虚拟继承区分开来 二.多态实现原理 多态则是通过继承.虚函数(virtual).指针来实现. class A { public: virtual void func() const { coust << "A::func