《Essential C++ 中文版》读书笔记

来源:互联网 发布:sql商务智能培训 编辑:程序博客网 时间:2024/05/01 10:08

 

Essential C++

Stanley B. Lippman

 

屋檐下的水滴--读书笔记系列

http://blog.csdn.net/dwater

 

面向过程的编程风格  Procedural Programming

1.  C++不允许改变改变reference所代表的对象,对reference的所有操作与对“reference所代表的对象”所进行的操作相同。

2.  by reference方式传递对象当作函数参数时,复制的将是对象的地址,函数中对该对象的所有操作都相当是对传入的对象进行间接操作。

3.  pointerreference的最重要差异是,pointer可以为空,使用前一定要确保其值非0,而reference必定代表某个对象,不必作此检查。

4.  编译器无法根据函数返回值型别来区分两个具有相同名称的函数,因为返回值型别无法保证提供我们一个足以区分不同重载函数的情境。

5.  由函数指针寻址出来的函数,其调用方式和一般函数相同。

6.  可以给函数指针赋予初值,函数名称即代表了函数的地址。

7.  标准的或项目专属的头文件应用尖括号扩住;用户自行提供的头文件则使用引号。

2002-6-3

泛型编程风格  Generic Programming

1.  Standard Template Library (STL) 主要由两种组件构成:容器container和泛型算法generic algorithm<通过function template技术,实现与容器及数值类型无关之功能>

2.  容器分类:<切记:vector可以是空的,数组则否>

序列式容器sequential container vector, list, deque……

关联式容器associative containermap, set, ……

3.  iteratorconst_iterator实际上是各个容器定义式内的嵌套nested 型别。

4.  使用泛型算法须#include <algorithm>,使用function object#include <functional>

5.  function object是某种class的实体对象,该classfunction call运算符进行了重载操作从而可使function object被当作一般函数来使用。令function call运算符成为inline,从而消除“通过函数指针来调用函数“时需付出的额外代价。

6.  function object adapter会对function object进行修改操作。

7.  绑定配接器binder adapter <bind1nd, bind2nd> 会使bineary function object变成unary function objectnegator adaper <not1, not2>会逆转function object的真伪值;另外一种有用的adapter 叫做instertion adapter <back_inserter, inserter, front_inserter> #include <iterator>

8.  map被定义为一对数值,其中key通常是个字符串,扮演索引角色,另一个数值是value

9.  任何一个key值在mapset内最多只有一份,若要多份相同key值,使用multimapmultiset

完成日期:2002-6-2

基于对象的编程风格  Object-Based Programming

1.在class内部定义的member   函数被自动视为inline函数。对inline函数而言,声明在class内部或外部并无区别,同non-member inline函数一样,它应于头文件中定义。

2Triangular t();被编译器视为一个函数定义!并不是声明或定义一个Triangular对象!

3.以某个class object作为另一个object的初值时,会发生default memberwise initialization<实际上是自动产生一个copy constructor>,可以为该class提供一个copy constructor来改变这一默认行为模式。

4.若有必要为class撰写copy constructor,则同样有必要为它撰写copy assignment operator,除非撰写copy constructor的目的仅仅是为了激活编译器实施NRV优化。

5.凡是在class主体以外定义的const member function,必须同时在声明与定义时都提供const关键字,const紧接于函数参数表之后。

6member function返回一个指向member datanon-const reference,实际上等于将该member data开放出去,允许程序在其它地方加以修改。由于函数可以根据参数const与否   而重载,故可以提供两份定义,一份为const版本,一份为non-const版本。

8.  设计class时,鉴定其const member function是一件很重要的事情!

9.  member data声明为mutable表明:对该member data的修改不会破坏class object的常数性。

10.              欲以一个对象复制出另一个对象,先确定两个对象是否相同是个好习惯。

11.              运算符的重载规则:不可以引入新的运算符,除了., .*, ::, ?:4个运算符,其它运算符皆可被重载;运算符的操作数operand不可改变;运算符的优先级不可改变;运算符函数的参数列中必须至少有一个参数为class型别。

12incrementdecrement运算符的前置及后置版本都可直接施行于class object其之上,编译器会自动为后置版产生一个int引数,其值必为0

13.所谓friend,具备了与class member function相同的存取权限,可以存取classprivate member

14.只要class设计者显示提供了copy assignment operator,它就会被用来取代default memberwise copy行为。

15.当编译器在编译过程中遇到函数调用,例如lt(ival)lt可能是函数名称,可能是函数指针,也可能是一个提供了function callfunction object。如果lt是个function object,编译器会在内部将此语句转化为:lt.operator(ival)

16function call可以接受多个运算符,通常将function object当作参数传给泛型算法。

17.为了取得某个member function的地址,只需对函数名称施以取址address-of运算符,同时,函数名称之前必须先以class object运算符加以修饰,而返回型别及参数表皆不需指明,如:void (classname::*mfptr) (int) = &classname::mfname;

18.注意所谓的maximal munch编译规则,如:static vector<vector<int> > seq; 两个”>”号之间必须加有空格,否则无法成功编译!

19pointer to member functionpointer to function的一个不同点是:前者必须通过同类的对象加以调用。.*符号是针对class object pointer to member selection运算符,->*符号是针对pointer to class objectpointer to member selection。使用它们时注意必须加上外围小括号!如:(classobject.*mfptr)(par);

                                                        完成日期:2002-6-18

 

面向对象编程风格   Object-Oriented Programming

1.  面向对象编程的两项最主要的特性是继承inheritance和多态polymorphism

2.  动态绑定Dynamic binding是面向对象编程风格的第三个独特概念,即找出实际被调用的究竟是哪一个派生类的函数。而静态绑定Static binding则在程序运行之前就决议出应该调用哪一个函数。

3.  多态和动态绑定的特性只有在使用pointerreference时才能发挥。

4.  staitic member function无法被声明为虚拟函数。

5.  任何一个类只要有纯虚拟函数,程序就会因其接口的不完整而无法为它产生任何对象,这种类只能作为派生类的子对象subobject之用,而且派生类必须为所有纯虚拟函数提供确切的定义。

6.  根据一般规则,凡基类定义有虚拟函数,其destructor应声明为virtual。但Stanley B.Lippman并不建议在这个基类中将其destructor 声明为pure virtual,而是提供空白定义:inline baseclass::~baseclass(){};

7.  对于public inheritance,继承而来的public成员和protected成员,无论在继承体系中的深度如何,都可视为派生类自身拥有的成员。

8.  每当派生类有某个member与其基类的member同名时,便会遮蔽住基类的那份member,若要在派生类中使用继承而来的那份member,必须使用class scope运算符加以修饰。

9.  不可为抽象基类定义任何对象,它们扮演的角色是每个派生类的subobject,基于此点,一般将抽象基类的constructor声明为protected而非public

10.              派生类之constructor,不仅必须为派生类之data members进行初始化操作,还需为其基类之data members提供适当的值。copy constructorcopy assignment operator的情形也一样,唯一棘手的是,必须明白调用基类的copy assignment operatorbase::operator = (rhs);

11.              改写基类提供的虚拟函数,派生类提供的定义其函数型别必须完全符合基类所声明的函数原型,包括参数列、返回型别、常量型const-ness。但是,对于“返回型别”有个例外:当基类的虚拟函数返回某个基类形式(通常是pointerreference)时,派生类中的同名函数可以返回该基类所派生出来的型别。

12.              在两种情况下,虚拟函数机制不会出现预期行为:1)在基类的constructordestructor内;2)使用基类的对象而非对象的pointerreference

13.              typeid运算符是RTTI的一部分,可以用它来查询多态化的class pointerclass reference,获得其所指对象的实际型别。typeid运算符会返回一个type_info对象,其中存储着与型别相关的种种信息。#include<typeinfo>

完成日期:2002-6-19

异常处理   Exception Handling

1.  初学者常犯的错误:将C++异常和segmentation fault或是bus error这类硬件异常混淆在一起。

2.  在异常处理机制终结某个函数之前,C++保证函数中的所有局部对象的destructor都会被调用。

3.  auto_ptr是标准程序库提供的class template,它会自动delete通过new表达式配置的对象。auto_ptrdereference运算符和arrow运算符予以重载,使得我们可以像使用一般指针一样使用auto_ptr对象。#include <memory>

4.  如果new表达式无法从程序的自由空间free store配置到足够的内存,它会抛出bad_alloc异常对象。如果要压抑不让bad_alloc异常被抛出,可以这么写:somepointer = new (nothrow) someclass; 这样,如果new动作失败,返回值为0

5.  标准程序库定义了一套异常类体系exception class hierarchy,其最根部是名为exception的抽象基类。exception声明有一个what()虚拟函数,会返回一个const char*,用以表示被抛出异常的文字描述。#include <exception>

6.  ostringstream class提供“内存内的输出操作”,输出到一个string对象上。当需要将多笔不同型别的数据格式转化为字符串表现式时,它尤其有用。ostringstream提供的str()可以返回对应的那个string对象。#include <sstream>

7.  iostream库也对应提供了istringstream class,如果需要将非字符串数据的字符串表现式转化为其实际型别,istringstream可派上用场。

8.  string class的转换函数c_str()会返回const char*

完成日期:2002-6-19

Essential C++ 中文版》读书笔记 http://blog.csdn.net/dwater

原创粉丝点击