13.6 基类的析构函数为何要声明为virtual?

解答:

用对象指针来调用一个函数,有以下两种情况:

  1. 如果是虚函数,会调用派生类中的版本。
  2. 如果是非虚函数,会调用指针所指类型的实现版本。

析构函数也会遵循以上两种情况,因为析构函数也是函数嘛,不要把它看得太特殊。 当对象出了作用域或是我们删除对象指针,析构函数就会被调用。

当派生类对象出了作用域,派生类的析构函数会先调用,然后再调用它父类的析构函数, 这样能保证分配给对象的内存得到正确释放。

但是,如果我们删除一个指向派生类对象的基类指针,而基类析构函数又是非虚的话, 那么就会先调用基类的析构函数(上面第2种情况),派生类的析构函数得不到调用。

例如:

class Foo
{
public:
void f();
}; class Bar: public Foo
{
public:
void f();
} Foo *p=new Bar();
p->f();

调用p->f()最后将会调用Foo::f(),这是因为p是指向Foo的指针,而f()不是虚函数。

为确保p->f()会调用继承关系最末端的子类的f()实现,我们需要将f()声明为虚函数。

现在,回到前面的析构函数。析构函数用于释放内存和资源。Foo的析构函数若不是虚拟的,那么,即使p实际上是Bar类型的,还是会调用Foo的析构函数。

这就是为何要将析构函数声明为虚拟的原因——确保正确调用继承关系最末端的子类的析构函数。

例如:

class Base{
public:
Base() { cout<<"Base Constructor"<<endl; }
~Base() { cout<<"Base Destructor"<<endl; }
};
class Derived: public Base{
public:
Derived() { cout<<"Derived Constructor"<<endl; }
~Derived() { cout<<"Derived Destructor"<<endl; }
};
int main(){
Base *p = new Derived();
delete p;
return ;
}

输出为:

Base Constructor
Derived Constructor
Base Destructor

上面结果表明,虽然基类指向的是派生类,但是调用析构函数释放p时,仍然只调用了基类的析构函数。

如果我们把基类的析构函数声明为虚析构函数,这会使得所有派生类的析构函数也为虚。 从而使析构函数得到正确调用。

将基类的析构函数声明为虚的之后,得到的输出是:

Base Constructor
Derived Constructor
Derived Destructor
Base Destructor

因此,如果我们可能会删除一个指向派生类的基类指针时,应该把析构函数声明为虚函数。 事实上,《Effective C++》中的观点是,只要一个类有可能会被其它类所继承, 就应该声明虚析构函数。

careercup-C和C++ 13.6的更多相关文章

  1. [CareerCup] 17.13 BiNode 双向节点

    17.13 Consider a simple node-like data structure called BiNode, which has pointers to two other node ...

  2. [CareerCup] 18.13 Largest Rectangle of Letters

    18.13 Given a list of millions of words, design an algorithm to create the largest possible rectangl ...

  3. [CareerCup] 13.1 Print Last K Lines 打印最后K行

    13.1 Write a method to print the last K lines of an input file using C++. 这道题让我们用C++来打印一个输入文本的最后K行,最 ...

  4. [CareerCup] 13.2 Compare Hash Table and STL Map 比较哈希表和Map

    13.2 Compare and contrast a hash table and an STL map. How is a hash table implemented? If the numbe ...

  5. [CareerCup] 13.3 Virtual Functions 虚函数

    13.3 How do virtual functions work in C++? 这道题问我们虚函数在C++中的工作原理.虚函数的工作机制主要依赖于虚表格vtable,即Virtual Table ...

  6. [CareerCup] 13.4 Depp Copy and Shallow Copy 深拷贝和浅拷贝

    13.4 What is the difference between deep copy and shallow copy? Explain how you would use each. 这道题问 ...

  7. [CareerCup] 13.5 Volatile Keyword 关键字volatile

    13.5 What is the significance of the keyword "volatile" in C 这道题考察我们对于关键字volatile的理解,顾名思义, ...

  8. [CareerCup] 13.6 Virtual Destructor 虚析构函数

    13.6 Why does a destructor in base class need to be declared virtual? 这道题问我们为啥基类中的析构函数要定义为虚函数.首先来看下面 ...

  9. [CareerCup] 13.7 Node Pointer 节点指针

    13.7 Write a method that takes a pointer to a Node structure as a parameter and returns a complete c ...

  10. [CareerCup] 13.8 Smart Pointer 智能指针

    13.8 Write a smart pointer class. A smart pointer is a data type, usually implemented with templates ...

随机推荐

  1. Spring事务隔离级别和传播特性

    相信每个人都被问过无数次Spring声明式事务的隔离级别和传播机制吧!今天我也来说说这两个东西. 加入一个小插曲, 一天电话里有人问我声明式事务隔离级别有哪几种, 我就回答了7种, 他问我Spring ...

  2. 【转】FTS抓包看蓝牙的SDP整个过程

    原文网址:http://blog.sina.com.cn/s/blog_69b5d2a50101f23c.html 1.概述   SDP是蓝牙的Service Discovery Protocol,用 ...

  3. error MSB3027: Could not copy "xxx.dll" to "xxx.dll". Exceeded retry count of 10. Failed.

    错误提示内容: C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(3363,5): error MSB302 ...

  4. Java程序版权保护解决方案

    通常C.C++等编程语言开发的程序都被编译成目标代码,这些目标代码都是本机器的二进制可执行代码.通常所有的源文件被编译.链接成一个可执行文件.在这些可执行文件中,编译器删除了程序中的变量名称.方法名称 ...

  5. 设计模式_Composite_合成模式

    形象例子: Mary今天过生日.“我过生日,你要送我一件礼物.”“嗯,好吧,去 商店,你自己挑.”“这件T恤挺漂亮,买,这条裙子好看,买,这个包也不错,买.”“喂,买了三件了呀,我只答应送一件礼物的哦 ...

  6. windows 下Python import 导入自定义模块

    周末在家研究这个东西,则找到解决方案. 费话少说,上代码 #定义一个自定义的函数,如下 #函数的名称必须是字母和数字的组合,不能用数字开头 #函数名后用小括号括住入参,可以用逗号分隔多个 #如果有返回 ...

  7. 企业移动互联网O2O微信支付流程图

    过去一周里最受关注的应该就是微信了,腾讯合作伙伴大会微信分论坛的火爆现场,没有亲临其境是无法想象的,近3000人报名,2000多人来到现场,试图进入只能容纳300人的会场…… 闲话不表,进入正题吧,本 ...

  8. javascript设计模式8

    桥接模式(将抽象与其实现隔离开来,以便二者独立变化) function sendInfo(element){ var id=element.id; ajax("GET"," ...

  9. V&View更新

    这几天一直在做V&View的更新工作,这次的更新是质的变化,表面界面变化不大,可是内部确有着翻天覆地的改变. 这几天我主要做了一下几件事: 1. 重新构思了vview的文章发布形式,之前使用k ...

  10. jexus asp.net Linux Web Server

    Jexus简介 Jexus web server for linux 是运行在Linux上的Web服务器.其安装和部署及其简单,直接支持Asp.net . 下载Jexus wget http://li ...