《Effective C++》笔记:III(转载)

  转自:http://www.cnblogs.com/destino74/p/3960802.html

  

  条款5:Know what functions C++ silently writes and calls

  

译:了解C++默默编写并调用哪些函数

在C++中,写一个空类,编译器会自动为它声明一个copy构造函数、一个copy assignment操作符和一个析构函数。如果没有声明任何构造函数,编译器也会自动声明一个default构造函数。

如下:

class Empty{};

这就相当于

class Empty{
public:
    Empty(){...}
    Empty(const Empty& rhs){...}
    ~Empty(){...}
    Empty& operator=(const Empty& rhs){...}
}

关于构造函数、copy构造函数的东西前两篇已经有介绍了。

条款6:Explicitly disallow the use of compiler-generated functions you do not want

译:若不想使用编译器自动生成的函数,就该明确拒绝

在一些场合,如果你不想对象内的某个函数被调用,可以把这些函数声明成private隐藏起来,这也是Java中实现工厂模式禁止new一个对象的伎俩。

但其实这并不保险,这些函数依然可以在成员函数或friend函数中被调用,当然,你可以人为的明令禁止调用这些函数。

书中提到的解决方法是只声明不定义。这就是我常犯的错误,声明了函数却没有定义函数体,在编译时会给出一个”无法解析的外部符号”这样的错误。

而利用这一点,就可以达到屏蔽自动生成的函数这一目的。

另一个方法就是实现一个类似Uncopyable接口的类,把需要隐藏的函数声明为私有函数,然后在派生类中私有继承这个Uncopyable类。

将成员函数声明为private且不实现,可禁止编译自动提供的函数。使用像Uncopyalbe这样的基类也能达到相同的目的。

条款7:Declare destructors virtual in polymorphic base classes

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

为什么要为多态基类声明virtual析构函数(虚析构函数)呢?原因是当一个指向派生类的基类指针被销毁时,会调用基类的析构函数,而这时派生类 的析构函数未能执行,派生类对象的成员变量 很可能没被销毁,这就为资源泄漏和莫名其妙的BUG提供温床,相应地增加你在调试上花的时间。

所以,在所有含virtual函数(虚函数)的类中,都应该声明virtual析构函数,这使它在不同的派生类中有不同的表现,从而让派生类中的资源在销毁时能被正确释放。

值得一提的是,当类中不含虚函数时,这往往意味着该类并不是设计来被继承,就不该声明虚析构函数,因为这从未声明一样。

书中提到了不应该继承任何不带virtual析构函数的类(如所有STL容器),在学习STL查阅资料时就了解到, 继承STL的作法给会造成各种糟糕的后果,因此自己在使用的时候总是以组合代替继承,就没有遇到过书中提到的、以及网上大量因继承STL而造成的问题。

带多态性质的基类应该声明一个virtual析构函数。任何带有virtual函数的类都应该拥有一个virtual析构函数。

如果一个类不希望作为基类被继承或不是为了具备多态性而设计,就不该声明virtual析构函数。(不应该设计STL容器派生类)

时间: 2024-10-31 05:59:19

《Effective C++》笔记:III(转载)的相关文章

Effective C++笔记06:继承与面向对象设计

关于OOP 博客地址:http://blog.csdn.net/cv_ronny 转载请注明出处! 1,继承可以是单一继承或多重继承,每一个继承连接可以是public.protected或private,也可以是virtual或non-virtual. 2,成员函数的各个选项:virtual或non-virtual或pure-virtual. 3,成员函数和其他语言特性的交互影响:缺省参数值与virtual函数有什么交互影响?继承如何影响C++的名称查找规则?设计选项有如些?如果class的行为

Effective C++笔记05:实现

条款26:尽可能延后变量定义式的出现时间 博客地址:http://blog.csdn.net/cv_ronny 转载请注明出处! 有些对象,你可能过早的定义它,而在代码执行的过程中发生了导常,造成了开始定义的对象并没有被使用,而付出了构造成本来析构成本. 所以我们应该在定义对象时,尽可能的延后,甚至直到非得使用该变量前一刻为止,应该尝试延后这份定义直到能够给它初值实参为止. 这样做的好处是:不仅可以避免构造(析构)非必要对象,还可以避免无意义的default构造行为. 遇到循环怎么办?此时往往我

Effective C++笔记04:设计与声明

条款18:让接口容易被正确使用,不易被误用 1,好的接口很容易被正确使用,不容易被误用.你应该在你的所有接口中努力达成这些性质. 2,"促进正使用"的办法包括接口的一致性,以及与内置类型的行为兼容. 3,"阻止误用"的办法包括建立新类型,限制类型上的操作,束缚对象值,以及消除客户的资源管理责任. 4,shared_ptr支持定制型删除器.这可以防范DLL问题,可以用来自动解除互斥锁. 条款19:设计class犹如设计type 博客地址:http://blog.csd

Effective C++笔记:构造/析构/赋值运算

条款05:了解C++默默编写并调用哪些函数 默认构造函数.拷贝构造函数.拷贝赋值函数.析构函数构成了一个类的脊梁,只有良好的处理这些函数的定义才能保证类的设计良好性. 当我们没有人为的定义上面的几个函数时,编译器会给我们构造默认的. 当成员变量里有const对象或引用类型时,编译器会不能合成默认的拷贝赋值函数:当一个基类把它的拷贝赋值函数定义为private时,它的派生类也不无生成默认的拷贝赋值函数,因为它无法完成基类成份的赋值. 条款06:若不想使用编译器自动生成的函数,就该明确拒绝 将拷贝构

Effective c++(笔记)之继承关系与面向对象设计

1.公有继承(public inheritance) 意味着"是一种"(isa)的关系 解析:一定要深刻理解这句话的含义,不要认为这大家都知道,本来我也这样认为,当我看完这章后,就不这样认为了. 公有继承可以这样理解,如果令class D以public 的形式继承了class B ,那么可以这样认为,每一个类型为D的对象同时也可以认为是类型为B的对象,但反过来是不成立的,对象D是更特殊化更具体的的概念,而B是更一般化的概念,每一件事情只要能够施行于基类对象身上,就一定可以应用于派生类对

Effective c++(笔记) 之 类与函数的设计声明中常遇到的问题

1.当我们开始去敲代码的时候,想过这个问题么?怎么去设计一个类? 或者对于程序员来说,写代码真的就如同搬砖一样,每天都干的事情,但是我们是否曾想过,在c++的代码中怎么样去设计一个类?我觉得这个问题可比我们"搬砖"重要的多,大家说不是么? 这个答案在本博客中会细细道来,当我们设计一个类时,其实会出现很多问题,例如:我们是否应该在类中编写copy constructor 和assignment运算符(这个上篇博客中已说明),另外,我们是让编写的函数成为类的成员函数还是友元还是非成员函数,

[Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+1}" 反射获取函数源代码的功能很强大,使用函数对象的toString方法有严重的局限性.toString方法的局限性ECMAScript标准对函数对象的toString方法的返回结果(即该字符串)并没有任何要求.这意味着不同的js引擎将产生不同的字符串,甚至产生的字符串与该函数并不相关. 如果函数

Effective c++(笔记)----类与函数之实现

上篇博客中集中说明了在设计一个类的时候常遇到的问题,当然博客中还夹杂着我随时想到的一些知识,发现自己写博客没很多人写的好,可能是自己语言不会组织,要么就是写的东西大家不愿意看,反正是有这方面的专业问题或者博客中有什么明显的错误和问题,大家提出来,我也好改进哈! 回归正题,这篇博客就大概的把Effective c++中类与函数这节看到的知识点做个笔记. 设计好一个类后,自己就要去实现这个类(实现类中的成员函数.友元.非成员函数等) 可能大家会遇到以下问题 1.在类的成员函数中,尽量避免返回内部数据

[Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式传递给eval函数以达到同样的功能.程序员面临一个选择:应该将代码表示为函数还是字符串?毫无疑问,应该将代码表示为函数.字符串表示代码不够灵活的一个重要原因是:它们不是闭包. 闭包回顾 看下面这个图 js的函数值包含了比调用它们时执行所需要的代码还要多的信息.而且js函数值还在内部存储它们可能会引用

java effective 读书笔记

java effective 读书笔记 [1]创建和销毁对象 1 静态工厂方法 就是“封装了底层 暴露出一个访问接口 ” 门面模式 2 多参数时 用构建器,就是用个内部类 再让内部类提供构造好的对象 3 枚举 singleton 不知道怎么操作,觉得意义不大 单例模式 4 私有化构造器不能实例化,也不可被子类继承 5 能用原生类的就尽量不用对象 [2]对于所有对象都通用的方法 reflexivity 自反性 symmetry 对称性 [3]类成员 降低可访问性 尽量把公有域 变成私有域,并提供