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. jQuery多库共存问题解决方法

    一.问题概述: 1.随着jQuery的流行,采用jQuery和$符为命名空间的js库越来越多,当然jQuery的$符也是参照的Prototype库的,所以当多个库同时以$符或者jQuery为命名空间时 ...

  2. Springboot用官方建议访问Html页面并接传值

    Springboot用官方建议访问Html页面并接传值 我们以前通常习惯用webapp来防止jsp页面,但是到了Springboot中,官方建议用Static文件夹来存放及静态的资源, 用templa ...

  3. 命令行下 初识 redis 入门教程

    1. redis-cli 命令行进入redis set,get, setex,给键值设置过期时间 setex name 10 DOG //设置name键 为 DOG 10秒后过期. setnx,判断值 ...

  4. android逆向基础:apk 反编译 重打包 重签名

    apk 反编译大家都比较熟悉,这里只做一个笔记. 1 反编译 apk apktool d perfect.apk 这样就把资源文件解压缩了, classes.dex 也反编译成了 smali 文件 2 ...

  5. Linux笔记-Linux下编辑器的简介

    在整个linux中,我们使用最多的编译器真的vim了,全名我也不说了,没有多大意义,我们就是通过它来写我们的代码的.如果你有强迫症的话,那么选择使用gedit我也是没话说的啦! 话说其实我也在使用一些 ...

  6. JAVA 方法 和Scanner

    方法:包含于类或对象中,是解决一类问题步骤的有序组合. 算法:解决一类问题的思想. Scanner next()与nextLine()区别 next(): 1.一定要读取到有效字符后才可以结束输入. ...

  7. Java泛型的逆变

    在上篇<Java泛型的协变>这篇文章中遗留以下问题——协变不能解决将子类型添加到父类型的泛型列表中.本篇将用逆变来解决这个问题. 实验准备 我们首先增加以下方法,见代码清单1所示. 代码清 ...

  8. 从父子组件的mounted钩子的同步执行与页面的异步渲染看nextTick的用法

    最近复习vue的时候遇到了一个很奇怪的问题,我们直接从实例中看: <div id="app"> <child ref="child">& ...

  9. Implicit super constructor xx() is undefined for default constructor. Must define an explicit constructor

      错误:Implicit super constructor xx() is undefined for default constructor. Must define an explicit c ...

  10. json的使用(JObect,JsonData,JArray)

    JObect与JsonData的区别 JsonData是JObect的简化版本 2.转换过程容易出的bug JsonData:当里面存在null就无法转换 解决方案: JsonData teamjd ...