careercup-C和C++ 13.6
13.6 基类的析构函数为何要声明为virtual?
解答:
用对象指针来调用一个函数,有以下两种情况:
- 如果是虚函数,会调用派生类中的版本。
- 如果是非虚函数,会调用指针所指类型的实现版本。
析构函数也会遵循以上两种情况,因为析构函数也是函数嘛,不要把它看得太特殊。 当对象出了作用域或是我们删除对象指针,析构函数就会被调用。
当派生类对象出了作用域,派生类的析构函数会先调用,然后再调用它父类的析构函数, 这样能保证分配给对象的内存得到正确释放。
但是,如果我们删除一个指向派生类对象的基类指针,而基类析构函数又是非虚的话, 那么就会先调用基类的析构函数(上面第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的更多相关文章
- [CareerCup] 17.13 BiNode 双向节点
17.13 Consider a simple node-like data structure called BiNode, which has pointers to two other node ...
- [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 ...
- [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行,最 ...
- [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 ...
- [CareerCup] 13.3 Virtual Functions 虚函数
13.3 How do virtual functions work in C++? 这道题问我们虚函数在C++中的工作原理.虚函数的工作机制主要依赖于虚表格vtable,即Virtual Table ...
- [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. 这道题问 ...
- [CareerCup] 13.5 Volatile Keyword 关键字volatile
13.5 What is the significance of the keyword "volatile" in C 这道题考察我们对于关键字volatile的理解,顾名思义, ...
- [CareerCup] 13.6 Virtual Destructor 虚析构函数
13.6 Why does a destructor in base class need to be declared virtual? 这道题问我们为啥基类中的析构函数要定义为虚函数.首先来看下面 ...
- [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 ...
- [CareerCup] 13.8 Smart Pointer 智能指针
13.8 Write a smart pointer class. A smart pointer is a data type, usually implemented with templates ...
随机推荐
- Spring编程风格
给自己使用的无需定义接口:即一个模块内部的都是封装的,定义接口并不会得到很多好处,变过几次实现?? “优先面向接口编程,而非实现” 不是必须,是优先: 给朋友(第三方)使用的定义接口:即要公开的功能, ...
- 【转】iOS中设置导航栏标题的字体颜色和大小
原文网址:http://www.360doc.com/content/15/0417/11/20919452_463847404.shtml iOS中设置导航栏标题的字体颜色和大小,有需要的朋友可以参 ...
- 【转】Android学习基础自定义Checkbox组件
原文网址:http://forum.maiziedu.com/thread-515-1-1.html heckbox组件是一种可同时选中多项的基础控件,即复选框,在android学习中,Checkbo ...
- 怎么找到MyEclipse->add struts capabilities
问:MyEclipse:我的工程右键可以MyEclipse->add struts capabilities之前有,后来不知怎么就没有了,谁知道怎么弄出来是struts 答:你已经add过一次了 ...
- Datatable转成Json方式两则
1, Asp.net C# 使用Newtonsoft.Json 实现DataTable转Json格式数据 1.这里下载:http://www.newtonsoft.com/products/json/ ...
- 导入showb时候出错--2015-12-4
[root@cache-02 ~]# /opt/coreseek/csftweb-bash: /opt/coreseek/csftweb: is a directory[root@cache-02 ~ ...
- [解决]Kali Linux DHCP自动获取IP失败 坑爹的VMWare桥接
root@kali:~# service networking restart [....] Running /etc/init.d/networking restart is deprecated ...
- Android实例-使用电话拨号器在移动设备上(官方)(XE8+小米2)
源文地址: http://docwiki.embarcadero.com/RADStudio/XE5/en/Mobile_Tutorial:_Using_the_Phone_Dialer_on_Mob ...
- magento 列表页显示产品属性值的几种调用方式
之前有人提到要在列表显示一些特定的属性,除了自带的名字,价格等.因为列表页和产品页都有一个同名的产品对象:$_product,而在产品页,$_product是直接可以用$_product->ge ...
- 依賴注入入門——Unity(一)
參考資料http://blog.csdn.net/m13666368773/article/details/7802126 背景介紹 在设计模式中,尤其是结构型模式很多时候解决的就是对象间的依赖关系, ...