Item 07 : 为多态基类声明virtual析构函数

 #include <iostream>
using namespace std; class Base {
public:
Base() : bValue() {}
virtual ~Base() { cout << "Base destructor" << endl; }
// ~Base() { cout << "Base destructor" << endl; }
virtual void print() {
cout << "print : base" << endl;
}
private:
int bValue;
}; class Derived : public Base {
public:
Derived() : dValue() {}
~Derived() {
cout << "Derived destructor" << endl;
}
void print() {
cout << "print : derived" << endl;
}
private:
int dValue;
}; int main() {
Base* p = new Derived();
p->print();
delete p;
}

注意Line 7和8,当基类的析构函数用的是Line7, 即基类析构函数是virtual时,Line32处执行delete p时,相当于调用p所指的析构函数,由于p是一个指向派生类对象的基类指针,且基类中析构函数是virtual的,所以满足了多态的发生条件,即此处调用的是派生类的析构函数Line19。派生类在析构的时候会自动调用其基类的析构函数,所以就有了下图的结果。

假如基类的析构函数不再是virtual的 (即将Line7注释掉,换成Line8),这样在Line32处调用delete p时, p本身是个基类指针,但是所指向的又是一个派生类对象。此时如果p所调用的函数是virtual的,那么p就直接调用派生类中的同名函数,即上面所描述的那样;若p所调用的函数不是virtual的,那它就老老实实的调用基类的函数。

所以将基类的析构函数换成non-virtual之后(即注释掉Line7换成Line8之后),结果如下:

这样导致的结果就是p所指的派生类对象只有基类部分得到释放,派生类对象中独属于派生类的部分仍留在堆上,导致内存泄漏。

==========================================================================================================

 #include <iostream>
using namespace std; class Point {
public:
Point(int xCoord, int yCoord);
~Point();
private:
int x, y;
}; class Point2 {
public:
Point2(int xCoord, int yCoord);
virtual ~Point2();
private:
int x, y;
}; class Point3 {
public:
Point3(int xCoord, int yCoord) : x(xCoord), y(yCoord) {}
~Point3() {}
private:
int x, y;
}; int main() {
cout << sizeof(Point) << endl;
cout << sizeof(Point2) << endl;
Point* p;
Point3 obj(,);
return ;
}

这段代码想要表达两个问题:

1. 虚函数由于vptr,vtbl,会占用一些额外空间。Point和Point2的差别就在于析构函数是否是virtual,输出结果为8,12.

2. 我把Point3这个class放在这的目的是想说明,对于Point和Point2这样的,类内部的构造函数、析构函数只有声明没有定义(都直接以;结尾的),在其成员函数-没有定义的情况下不妨碍对它们求sizeof和定义指针(L31),但是它们不能定义对象(像L32那样)。

============================================================================================================

Item 29 : 为“异常安全” 而努力是值得的

经验:异常安全函数即使发生异常也不会泄漏资源或允许任何数据结构败坏。这样的函数区分为三种
可能的保证:
基本型-->发生异常,程序处于某个合法状态
强烈型-->发生异常,程序处于原先状态
不抛异常型-->承诺绝不抛出异常 class PrettyMenu {
public:
void changeBackground(istream& imgSrc);
private:
Mutex mutex; //由于这个class希望用于多线程环境,所以它有这个互斥器作为并发控制之用
Image* bgImage; //目前的背景图像
int imageChanges; //背景图像被改变的次数
}; void PrettyMenu::changeBackground(std::istream &imgSrc) {
lock(&mutex); //取得互斥器
delete bgImage; //摆脱旧的背景图像
++imageChanges; //修改图像变更次数
bgImage = new Image(imgSrc); //安装新的背景图像
unlock(&mutex); //释放互斥器
} 解析:
泄漏资源:new Image(imgSrc) 导致异常的话,互斥器就不会 unlock
数据败坏:new Image(imgSrc) 导致异常的话,bgImage指向一个已删除的对象,imageChanges 也已被累加

ref

Effective C++ Notes的更多相关文章

  1. 转:Effective c + + notes

    补充自己的. 转自:http://blog.csdn.net/ysu108/article/details/9853963#t0 Effective C++ 笔记 目录(?)[-] 第一章 从C转向C ...

  2. ToDo系列

    leetcode http://www.cnblogs.com/TenosDoIt/tag/leetcode/ http://tech-wonderland.net/category/algorith ...

  3. Effective Objective-C 2.0 Reading Notes

    1. Literal Syntax NSString *someString = @"Effective Objective-C 2.0"; NSNumber *someNumbe ...

  4. Effective Java Index

    Hi guys, I am happy to tell you that I am moving to the open source world. And Java is the 1st langu ...

  5. Notes on <Assembly Language step by step>

    By brant-ruan Yeah, I feel very happy When you want to give up, think why you have held on so long. ...

  6. Reading Notes of Acceptance Test Engineering Guide

    The Acceptance Test Engineering Guide will provide guidance for technology stakeholders (developers, ...

  7. A Java back-end engineer's study notes

    loveincode's notes 学习工作中的一些记录,收藏. 人气很高的链接库 计算机基础相关笔记 操作系统 , 编译原理 , 计算机网络 , 互联网协议... 常用数据结构与算法 Java 实 ...

  8. Notes of O_DIRECT flag

    What is O_DIRECT Starting with kernel 2.4, Linux allows an application to bypass the buffer cache wh ...

  9. 高性能服务器设计(Jeff Darcy's notes on high-performance server design

    高性能服务器设计(Jeff Darcy's notes on high-performance server design 我想通过这篇文章跟大家共享一下我多年来怎样开发“服务器”这类应用的一些想法和 ...

随机推荐

  1. mono上部署web程序初体验

    早就想体验一下mono,但一直琐事缠身.难得有时间,便在网上一通狂搜mono相关的资料. 如果想使用Apache服务器,只能使用mod_mono的方式,这里有详细的介绍.这种方式有点繁琐,需要安装一大 ...

  2. 四大组件之Activity Task任务栈4种启动模式

    1.启动模式 standard,创建一个新的Activity. singleTop,栈顶不是该类型的Activity,创建一个新的Activity.否则,onNewIntent. singleTask ...

  3. 由UI刷新谈到线程安全和Android单线程模型

    1.为什么说invalidate()不能直接在线程中调用? Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在非UI主线程中调用,因为他是违背了单线程模型:A ...

  4. PHP之string之str_pad()函数使用

    str_pad (PHP 4 >= 4.0.1, PHP 5, PHP 7) str_pad - Pad a string to a certain length with another st ...

  5. 快速排序分析及实现(C++)

    目录 快速排序算法分析及实现(C++) 算法思想 快速排序步骤 优点分析 C++语言实现 快速排序算法分析及实现(C++) 算法思想 ​ 把n个元素划分为三段:左端Left,中间段middle和右端r ...

  6. 入门系列之在Ubuntu 14.04上备份,还原和迁移MongoDB数据库

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由信姜缘 发表于云+社区专栏 MongoDB是最受欢迎的NoSQL数据库引擎之一.它以可扩展,强大,可靠和易于使用而闻名.在本文中,我们 ...

  7. 使用JS传递数组型数据回服务器

    //为数组添加一个方法,判断某个值是否存在于数组中 Array.prototype.in_array = function (e) { for (i = 0; i < this.length & ...

  8. centos下对文件某些特定字符串分组统计出现次数

    假如现有数据: { "@timestamp": "2018-10-13T21:55:58+08:00", "remote_addr": &q ...

  9. [转]ASP.NET web API 2 OData enhancements

    本文转自:https://www.pluralsight.com/blog/tutorials/asp-net-web-api-2-odata-enhancements Along with the ...

  10. NodeJS,MongoDB,Vue,VSCode 集成学习

    NodeJS,MongoDB,Vue,VSCode 集成学习 开源项目地址:http://www.mangdot.com