Effective C++学习笔记

Effective C++再次浏览的一些笔记,用于以后复习,温故知新

chapter pre:一些小细节///

①.declaration, definition, inialization(在construction中explicit阻止编译器执行隐士类型转换),

拷贝构造和拷贝赋值调用的区别决定于是否有新对象的创建

Widget A; Widget B(A); // copy construction,     A = B; // copy assignment; 

Widget A; Widget B = A; // copy construction,        void Fun(Widget a);// passed by value, call copy construction

二元操作符重载函数用到的两个参数命名, lhs(left-hand-side), rhs(right-hand-side)

C++ 支持的编程范式(programming paradigm):procedual、object-oriented、generic、functional、metaprogramming

STL已经玩熟后可以多熟悉Boost

//条款2

1.对于常量,用const对象替代#define提供类型检测而不是预编译时候的直接替换更安全,而且可以封装到类型里面, 而enum定义封装于类中更像#define因其不可取地址

2.#define定义的函数宏最好用inline性质的模板函数代替,省去了每个参数的括号,也不用担心参数自运算带来的错误

eg:  #defiine CALL_WITH_MAX(a,b)  fun((a)>(b) ? (a) : (b))--> template<typename T> inline void callwithmax(const T& a, const T& b) { f( a > b ? a : b); }

//条款3const的用途

1. const Widget * ptr == Widget const * ptr;   区分const widget * const ptr; STL中有const_iterator类似 Widget * const ptr;

2. 用于函数自身\return\paras,   if ( a*b = c ) // operator=的常量返回值用途;

3.用于成员函数时,在定义了const版本后,实现non-const版本就可以调用const版本避免的代码重复, non-const 版本的函数可以调用const函数, 反之则不然!! 

//条款4确定对象在使用前必须初始化

****一切对象在使用前都应初始化,尤其是成员变量****

1.成员变量的声明顺序决定member initialization list的实际顺序

2.C++对"定义于不同编译单元内的non-local static对象"的初始化顺序无明确定义,所有为了避免"跨编译单元的初始化问题",应该用local static对象代替non-local static 对象,一个很好的使用例子就是singleton;   static 对象析构函数在main函数结束时被调用;

条款5//

1.空类型编译器默认实现(F4^_^): ctor, copyctor, dtor, copy assignmentOptor, 默认的ctor和copy assignmentOptor以值拷贝的方式拷贝每一个non-static成员;

2.当存在const成员, 当存在reference成员,当父类的赋值运算符函数为private时,这三种情况编译器都不会实现copy assignmentOptor, 需要自己手动实现,以为const和reference成员在初始化过后不能修改,所有避免默认生成的operator=修改其值编译器拒绝生成该函数了!

3.单例的实现机制①private声明F4(类的外部不能访问,编译错误),②并且不加以实现(避免成员函数或者友元类访问,链接错误);

///条款9虚函数相关//

1.设计多态性质的基类必须要虚析构函数(指向子类对象的基类指针调用derived类的析构), 原则为: 如果有virtual成员函数就应该有虚析构; 

2.不作为多态性质的基类就不应该声明virtual函数,防止虚函数表生成增加存储负担, 虚表增加了指针的长度,并且降低或者移除了该对象指针的移植性

3.在作为多态基类的构造和析构函数中避免调用本类的虚函数,应为此种调用绝不会下降到derived类中实现的版本!!切记切记

***************3资源管理*****************

1.获得资源后立即放入管理器对象。RAII : Resource Acquisition Is Initialization.

2.管理对象用析构函数来确保资源被释放

3.常用的trick: 抑制copying,采用引用计数,实现深拷贝等

4.提供资源获取接口,类型转换可以采用隐士或者显示转换

5.new -- delete,   new array [ ] -- delete [ ].

***************4设计建议****************

1.让接口更容易被正确的使用

2.尽量使自己的定义的type的行为与内置type行为一致,除非有更好的理由.

3.除了内置类型,STL中迭代器和函数对象应该使用pass-by-value外,最好其他的都用pass-by-reference-to-const来提高传递效率和避免[类型切割问题]!!

4.永远不要让函数返回指向一个局部对象的指针或者引用,当作为左值返回时候用Obj&对象的引用,当作为右值返回时用const Obj对象的拷贝形式.

5.再设计客户使用类型时候成员变量最好全部采用private来体现封装性, protect对于derived class仍然可见所有它不比public具有更好的封装性.

6."<<",">>"必须作为non-member函数,eg:friend std::ostream& operator << ( std::ostream& o, const Matrix& mat) {  o<< "mat" << "xxx" << "***"; return o; }

7.关于条款24需要代码验证!

****************5实现*******************

1.尽量延后变量定义式的出现,增加程序的清晰度和易维护性。【eg:循环内外变量的取舍问题】

2.在注重效率的代码中避免dynamic_cast,基于字符串名词对比的实现方案中如果继承体系复杂多次使用strcmp效率低下。const_cast:去常,static_cast:强迫隐士转换,reinterpret_cast:低级转型(实际动作取决于编译器,会让代码失去可移植性,不用最好);

3.条款29:为异常安全而努力需要在项目代码中实践!

4.inline建议:小型且频繁调用的函数. inline弊端①增加目标码 导致代码膨胀问题,②大部分调试器都无法调试,③一旦修改inline函数导致客户端程序需要重新编译,反之则仅需要重新链接就行.  模板函数在头文件中也不能轻易的声明为inline;

5.尽量减少编译依赖关系(compilation dependency),①前向申明+指针或者引用替代对象 ②Interface classes.

****************6继承与面向对象*********

1.public 继承意味着is-a, 在能使用父类的情况永远可以使用派生类;

2.绝对不要重新定义继承而来的non-virtual函数.体会1.   静态绑定时对象的行为由指向它指针或者引用类型决定的. 

3.derived class中不重新定义base的虚函数将继承父类的虚函数实现,该函数的virtual关键字毫无用处,反而降低了效率一无是处;

4.决不能通过重新定义继承而来的缺省参数值来做一些动作!缺省参数值是静态绑定由静态类型决定,而虚函数绑定由实际类型动态绑定. [函数和参数由两方面组合而成]

5.条款33:避免遮掩继承而来的名称, ①using Base::Fun()//base中所有名为Fun的接口对子类可见, ②forwarding functions(定义转交函数) { Base::Fun(); }

6.public继承下, pure virtual=接口继承, impure virtual = 接口继承 + 缺省实现继承, non-virtual = 接口继承 + 强制性实现继承(不变更)[eg:飞机继承体系案例]

7.虚函数以外的其他选择: ①NVI(non-virtual-interface)手法充当wrapper函数,base中nvi函数调用私有虚函数,derived中仅实现private的虚函数即可.②策略模式strategy,用于各种伤害计算的实例

8.virtual继承可以解决钻石继承的多个成员变量实例问题

PS:模板和泛型编程内容在工作中用到不多,所有留到以后细读;



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值