资源预览内容
第1页 / 共45页
第2页 / 共45页
第3页 / 共45页
第4页 / 共45页
第5页 / 共45页
第6页 / 共45页
第7页 / 共45页
第8页 / 共45页
第9页 / 共45页
第10页 / 共45页
亲,该文档总共45页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
<p><p>&lt;p&gt;&amp;lt;p&amp;gt;Effective C+ 学习笔记 BY. SnowVirus 导读(术语解释) ?STL 标准模板库(Standard Template Libry),是C+标准程序库 的一个部分,致力于容器(如 vector,list,set,map)、迭代器(如 vector:iterator,set:iterator等)、算法(如 for_each,find,sort等等)及相关机能。 ?TR1(“Technical Report 1”)是一份规范,描述加入C+标准程序 库的诸多新机能。所有的TR1组件都被置于命名空间tr1内,后者 嵌套于命名空间std内。 ?Boost是个组织,也是一个网站(http:/boost.org)。 ?Explicit用来阻止编译器执行隐式类型转换,但可以进行显示类 型转换。 第一章:让自己习惯C+ ? 条款01:视C+为一个语言集合(View C+ as a federation of languages) C。说到底C+仍是以C为基础。区块(blocks)、语句(statements)、 预处理器(preprocessor)、内置数据类型(built-in data types)、数 组(arrays)、指针(pointers)等统统来自C。 Object-Oriented C+。Classes(包括构造函数和析构函数),封装 (encapsulation)、继承(inheritace)、多态(polymorphism)、virtual 函数(晚捆绑)等等。 Template C+。泛型编程部分。 STL。 C+ 高效编程守则视状况而变化,取决于你使用C+的哪一部分。 ? 条款02:尽量以const,enum,inline替换 #define ? Prefer consts enums and inline to #defines #define 可能并不进入符号表(symbol table)。 Const: ? 常量指针(constant pointers) 例:不变的char* - based 字符串(最好使用string) &amp;amp;#187; Const char* const authorName = “Scott Meyers”; ? Class专属常量 为了确保此常量至多只有一份实体,必须让它成为一个static成员: &amp;amp;#187; Class GamePlayer &amp;amp;#187; Private: &amp;amp;#187; static const int NumTurns = 5 ; /常量声明 &amp;amp;#187; ; 注意:只要不取它的地址,你可以声明并使用它们而无需提供定义。 如果你取某个class专属常量的地址或者编译器报错,你就必须提供定义 。 如:const int GamePlayer:NumTurns; 由于class常量已在声明时获得初值(static),因此定义时不用再设初值。 如果编译器还不允许这样,可以使用在声明外面定义赋予初值。 如:const int GamePlayer:NumTurns = 5; 如果还是报错,可以选择用 enum 关键字。 如:enum NumTurns = 5; ? Template Inline代替宏 ? 对于形似函数的宏(macros),最好改用inline函数替换#defines. ? 对于单纯常量,最好以const对象或enums替换#defines. ? 条款03:尽可能使用const Use const whenever possible 如果关键字const出现在星号左边,表示被指类型是常量;如果出现 在星号右边,表示指针自身是常量;如果在星号两边,表示被指类 型和指针两者都是常量。 Const最具有代表性的是函数声明时的应用。Const可以和函数返回 值、各参数、函数自身产生关联。 Const 成员函数 ? 1)它们使class接口比较容易理解。 ? 2)它们使“操作const对象”成为可能。 如果函数的返回类型是个内置类型,那么改掉函数返回值就不可能 合法。 Bitwise constness(physical constness) ? 成员函数只有在不更改对象的任何成员变量(static除外)时才可以说是 const。也就是说它不更改对象内任何一个位(bit)。 Logical constness ? 一个const成员函数可以修改它所处理的对象内某些bits,但只有在客户 端侦测不出的情况下才可以。 Mutable(可变的)关键字可以释放掉non-static成员变量的bitwise constness约束; ?在const和non-const成员函数中避免重复 Const成员函数调用non-const成员函数是一种错误行为,因为对象 有可能因此被改动。 Const_cast ? 用法:const_cast(expression) 该运算符用来修改类型的const或volatile属性。 常量指针被转化成非常量指针,并且仍然指向原来的 对象; 常量引用被转换成非常量引用,并且仍然指向原来的 对象; 常量对象被转换成非常量对象; Static_cast ? 用法:static_cast(expression) 该运算符把expression转换为type-id类型,但没有 运行时类型检查来保证转换的安全性。 C+ primer 里说明在进行隐式类型转换都用 &amp;amp;#187; Int I = Static_castf; / float f = 1.42f; ? 总结 将某些东西声明为const可帮助编译器侦测出错误的用法。Const 可 被施加于任何作用域内的对象、函数参数、函数返回类型、成员函 数本体。 编译器强制实施 bitwise constness,但你编写程序时应该使用“概 念上的常量性”(conceptual constness)。 当const 和 non-const 成员函数有着实质等价的实现时,令 non- const版本调用 const版本可避免代码重复。 ? 条款04:确定对象被使用前已被初始化 Make sure that object are initialized befor theyre used. 读取未初始化的值会导致不明确的行为。 ?对象的初始化何时一定发生,何时不一定发生。 对于无任何成员的内置类型,必须手工完成此事。 对于内置类型以外的任何其他东西,初始化责任落在构造函数 (constructors)身上。确保每一个构造函数都将对象的每一个成员 初始化。 C+规定,对象的成员变量的初始化动作发生在进入构造函数本体之 前。 构造函数的最佳写法是,使用 member initialization list(成员初 始化表)如: ? ABEntry:ABEntry(char ? 或者使用空基类(empty base class)声明空函数来继承。 ? 条款07:为多态基类声明Virtual析构函数 ? Declare destructors virtual in polymorphic base classes. C+明确指出,当derived class对象经由一个base class指针被删除 ,而该base class带着一个non-virtual析构函数,其结果未有定义- -实际执行时通常发生的是对象的derived 成分没被销毁。 ? 方法:给base classes 定义一个 virtual 析构函数。 ? 任何class只要带有virtual 函数都几乎确定应该有一个virtual析构函数 。 欲实现出virtual函数,对象必须携带某些信息,主要用来在运行期 决定哪一个virtual函数被调用。这份信息通常由一个所谓vptr( virtual table pointer)指针指出。 令class带一个pure virtual(纯虚)析构函数会导致abstract(抽象 )classes -也就是不能被实体化(instantiated)的class. 总结 ? Polymorphic(带多态性质的)base classes 应该声明一个 virtual析构函 数。如果 class带有任何virtual函数,它就应该拥有一个virtual析构函 数。 ? Classes 的设计目的如果不是作为base classes使用,或不是为了具备 多态性(polymorphic),就不该声明Virtual析构函数。 ? 条款08:别让异常逃离析构函数 ? Prevent exception from leaving destructors 当析构函数发生异常时,有以下2中解决办法 ? 如果抛出异常就结束程序,通常通过调用 abort完成 DBConn:DBConn() &amp;amp;#187; Try ; &amp;amp;#187; Catch() &amp;amp;#187; std:abort(); &amp;amp;#187; ? 吞下因调用析构函数而发生的异常; 总结 ? 析构函数绝对不要吐出异常。如果一个被析构函数调用的函数可能抛出 异常,析构函数应该捕捉任何异常,然后吞下它们(不传播)或结束程序 。 ? 如果客户需要对某个操作函数运行期间抛出的异常做出反应,那么class 应该提供一个普通函数(而非在析构函数中)执行该操作。 ? 条款09:绝不在构造和析构过程中调用Virtual函数 ? Never call virtual functions during construction or destruction Base class构造期间 virtual 函数绝不会下降到 derived classes阶 层。(在base class构造期间,virtual函数不是virtual函数) ? 条款10:令operator = 返回一个 reference to *this ? Have assignment operator return a reference to *this. 关于赋值,你可以把它们写出连续形式: ? Int x,y,z; ? X = y = z =15; 同样的,赋值采用的是右结合方法,所有上述连续赋值解析为: ? X =(y = ( z = 15); 为了实现连续赋值,赋值操作符必须返回一个reference指向操作 符的左侧实参。 ? 条款11:在operator= 中处理“自我赋值” Handle assignment to self in operator=. 确保当对象自我赋值时 operator= 有良好的行为。其中技术包括比 较“来源对象”和“目标对象”的地址、精心周到的语句顺序、以及 copy-and-swap。 确定任何函数如果操作一个以上的对象,而其中多个对象是同一个 对象时,其行为仍然正确。 ? 条款12:复制对象时勿忘其每一个成分 Copy all parts of an object 当你编写一个copying 函数,请确保(1)复制所有local成员变量,(2) 调用所有base classes内的适当的copying函数。 Copying 函数应该确保复制“对象内的所有成员变量”及“所有base class成员”。 不要尝试以某个copying函数实现另一个copying函数。应该将共同 功能放进第三个函数中,并由两个copying函数共同调用。 第三章:资源管理 ?所谓资源就是,一旦用了它,将来必须还给系统。C+程序中最 常使用的资源就是动态分配内存(如果你分配内存却从来不曾归 还它,会导致内存泄露),但内存只是你必须管理的众多资源之 一。 ? 条款13:以对象管理资源 Use object to manage resources. 把资源放进对象内,我们便可依赖C+的“析构函数自动调用机制”确 保资源被释放。 STL标准程序库提供的auto_&amp;lt;/p&amp;gt;&lt;/p&gt;</p></p>
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号