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. JavaScript设计模式-4.继承和聚合

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. 浅谈内存映射I/O(MMIO)与端口映射I/O(PMIO)的区别

    最近在看NVMeDirect和SPDK的源码,觉得有必要梳理一下MMIO和PMIO的区别.关于MMIO和PMIO,维基百科上是这么讲滴, Memory-mapped I/O (MMIO) and po ...

  3. Ubuntu双网卡不双待攻略

    特别不喜欢基于Windows的工作环境,这对一个Unix/Linux程序员来说,可以说是一种信仰.要不是电子邮件客户端被牢牢绑定在可恶的Outlook 2013上(因为加密邮件要求, 想使用Thund ...

  4. iOS开源项目周报0309

    由OpenDigg 出品的iOS开源项目周报第十期来啦.我们的iOS开源周报集合了OpenDigg一周来新收录的优质的iOS开源项目,方便iOS开发人员便捷的找到自己需要的项目工具等.LazyScro ...

  5. android 模拟器无法启动问题

    很早之前就碰到过Android Studio模拟器无法启动的问题,今天终于尝试去解决了下,下面将我解决的方法记录下. 模拟器报错信息为: emulator: ERROR: x86 emulation ...

  6. 六、yarn运行模式

    简介 spark的yarn运行模式根据Driver在集群中的位置分成两种: 1)yarn-client 客户端模式 2)yarn-cluster 集群模式 yarn模式和standalone模式不同, ...

  7. 用户登录注册(安全)(常规、FB、google、paypal) 实战

    /* 用户登录界面 */elseif ($action == 'login'){    if($_SESSION['user_id'])    {        ecs_header("Lo ...

  8. Mavean多工程依赖项目

    前言 本篇文章基于Java开发小技巧(二):自定义Maven依赖中创建的父工程project-monitor实现,运用我们自定义的依赖包进行多工程依赖项目的开发. 下面以多可执行Jar包项目的开发为例 ...

  9. 2.java设计模式-抽象工厂模式

    抽象工厂模式简介: 每一个模式都是针对某一种问题的解决方案.抽象工厂模式与工厂模式最大的区别在于,工厂模式针对的是一个产品等级结构,而抽象工厂模式面对的是多个产品等级结构,即产品族的概念. 这里讲解一 ...

  10. 一图解析 React组件生命周期 (React Component Lifecycle)

     React LifeCycle v1 参考官方文档作成 可放大  参考:https://reactjs.org/docs/react-component.html 数字补丁数字补丁数字补丁数字补丁数 ...