Effective C++ Notes

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

 1 #include <iostream>
 2 using namespace std;
 3
 4 class Base {
 5 public:
 6     Base() : bValue(1) {}
 7     virtual ~Base() { cout << "Base destructor" << endl; }
 8     // ~Base() { cout << "Base destructor" << endl; }
 9     virtual void print() {
10         cout << "print : base" << endl;
11     }
12 private:
13     int bValue;
14 };
15
16 class Derived : public Base {
17 public:
18     Derived() : dValue(100) {}
19     ~Derived() {
20         cout << "Derived destructor" << endl;
21     }
22     void print() {
23         cout << "print : derived" << endl;
24     }
25 private:
26     int dValue;
27 };
28
29 int main() {
30     Base* p = new Derived();
31     p->print();
32     delete p;
33 }

注意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所指的派生类对象只有基类部分得到释放,派生类对象中独属于派生类的部分仍留在堆上,导致内存泄漏。

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

 1 #include <iostream>
 2 using namespace std;
 3
 4 class Point {
 5 public:
 6     Point(int xCoord, int yCoord);
 7     ~Point();
 8 private:
 9     int x, y;
10 };
11
12 class Point2 {
13 public:
14     Point2(int xCoord, int yCoord);
15     virtual ~Point2();
16 private:
17     int x, y;
18 };
19
20 class Point3 {
21 public:
22     Point3(int xCoord, int yCoord) : x(xCoord), y(yCoord) {}
23     ~Point3() {}
24 private:
25     int x, y;
26 };
27
28 int main() {
29     cout << sizeof(Point) << endl;
30     cout << sizeof(Point2) << endl;
31     Point* p;
32     Point3 obj(1,2);
33     return 0;
34 }

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

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

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

时间: 2024-11-08 05:56:38

Effective C++ Notes的相关文章

Effective C++ Notes(读书笔记)

1,视C++为一种语言联邦,大致分为4个部分: A)C.说到底C++仍是以C为基础.区块.语句.预处理器.内置数据类型.数组.指针等等统统来自C. B)Object-Oriented C++.这部分也就是C with Classes所诉求的:classes(包括构造函数和虚构函数).封装.继承.多态,虚函数等等. C)Template C++.这是C++的范型编程部分,tamplates威力强大,它给我们带来了崭新的编程范型,也就是所谓的TMP模板元编程. D)STL.STL是个template

Effective C++读书笔记 Part1

##Effective C++ Notes ### Part I. Accustoming Yourself to C++ ####1. View C++ as a federation of languages- C++ is a multi-paradigm programming language with paradigms including procedure oriented, object oriented and generic programming with their o

Effective C++读书笔记 Part2

Effective_CPP_Note2 :first-child { margin-top: 0; } blockquote > :last-child { margin-bottom: 15px; } h1 { text-transform: uppercase; font-weight: bold; border-bottom: 1px solid; } h2 { border-bottom: 1px solid; } h3, h4, h5, h6 { border-bottom: none

《GCD 实现同步锁》-07-多线程

@MicroCai 2015-03-03 23:18 字数 6539 阅读 202 Effective Objective-C Notes:GCD 实现同步锁 Archives iOS <Effective Objective-C Notes>系列博文整理自<Effective Objective-C 2.0> 如果您觉得我的博客对您有帮助,请通过关注我的新浪微博  MicroCai 支持我,谢谢! 本文名为<GCD 实现同步锁>,内容不止于锁.文章试图通过 GCD 同

Read Notes:[Effective Java] Consider static factory methods instead of Constructors

Providing a static method instead of a public constructor has both advantages and disadvantages. One advantage of static factory methods is that, unlike constructors,they have names. A Second advantage of static factory methods is that, unlike constr

reading notes —— effective Java;目录结构,便于复习与查找

第1章 引言 第2章 创建和销毁对象 第1条:考虑用静态工厂方法代替构造器 第2条:遇到多个构造器参数时要考虑用构建器 第3条:用私有构造器或者枚举类型强化Singleton属性 第4条:通过私有构造器强化不可实例化的能力 第5条:避免创建不必要的对象 第6条:消除过期的对象引用 第7条:避免使用终结函数 第3章 对于所有对象都通用的方法 第8条:改写equals时请遵守通用约定 第9条:改写equals时总要改写hashCode 第10条:始终要改写toString 第11条:谨慎地改写clo

Steps to Writing Well----Reading Notes

Steps to Writing Well--Reading Notes */--> Steps to Writing Well--Reading Notes Table of Contents 1. Chapter 1 Prewriting 2. Chapter 2 The thesis statement 3. Chapter 3 The body paragraphs 4. Chapter 4 Beginnings and Endings 5. Chapter 5 Drafting and

《Effective C++》读书笔记汇总

我之前边读<Effective C++>边写下每个条款的读书笔记,这一版是C++11之前的版本.这里我将每个条款令我印象深刻的点小结一下. 1.C++包括:Plain C(面向过程).OOP(面向对象).模板(泛型和模板元编程).STL(C++标准库). 2.用inline.enum.const代替#define.#define定义的宏,一旦复杂起来,高手都很难掌控.不要带入C的习惯. 3.灵活使用const前缀.不需要进行改变的数据加上const前缀.指针的const前缀有两种形式,cons

Effective Java之内部类

Effective Java中对类的权限,接口等的要求,总结起来就是够用就行,不要赋予过多的访问权限,类的定义也是,如果某个类只会在类的内部使用,那就将该类定义为内部类吧. 内部类分为四种: 1.静态内部类:静态内部类就是在class前面多了static关键词的内部类,这种类和类的静态方法和静态变量一样,针对类本省进行操作,在静态内部类中可以随意访问其所在类的静态方法和静态变量. 2.非静态内部类:和静态内部类相对于,其实在类内部定义的所有东西只是受到访问修饰符的限制,所以非静态内部类和类的非静