Effective Cpp
1.让自己习惯C++
将构造函数声明为explicit,可阻止被用来执行隐式类型转换,仍可被用来进行显示类型转换 class C{ public: explicit C(int x); } Accustoming Yourself to C++ # 1.View C++ as a federation of languages # C Object-Oriented C++ Template C++ STL 2.Perfer consts,enums,and inlines to#defines # 一旦宏被定义,在其后的编译过程中一直有效,除非在某处被#undef const double AspectRatio = 1.653; const char* const authorName = "Scott Meyers"; const std::string authorName("Scott Meyers"); 对于单纯常量,最好以const对象或者enums替换#defines class GamePlayer{ private: static const int NumTurns = 5;//新一点的编译器才支持声明时定义 int scores[NumTurns]; } class GamePlayer{ private: enum{ NumTurns = 5}; int scores[NumTurns]; } 对于形似函数的宏(macros),最好改用inline函数替换#defines
2.构造、析构、赋值运算
Constructors,Destructors,and Assignment Operators # 5.Know what functions C++ silently writes and calls # 编译器可以暗自为class创建default构造函数 、copy构造函数、copy assignment操作符,以及析构函数 区分copy构造和copy赋值 class Widget{ public: Widget();//default构造 Widget(const Widget& rhs);//copy构造 Widget& operator=(const Widget& rhs);//copy assignment操作符 }; Widget w1;//default构造 Widget w2(w1);//copy构造 w1 = w2;//copy assignment操作符 Widget w3 = w2;//copy构造 通过是否真正产生新的对象来区分copy构造和拷贝赋值 6.Explicitly disallow the use of compiler-generated functions you do not want # 所有编译器产出的函数都是public,为驳回编译器自动提供的机能,可将相应的成员函数声明为Private并且不予实现 #define Q_DISABLE_COPY(Class) \ Class(const Class &) = delete;\ Class &operator=(const Class &) = delete; class Uncopyable { protected://允许derived对象构造和析构 Uncopyable(){} ~Uncopyable(){} private: Uncopyable(const Uncopyable&); Uncopyable& operator=(const Uncopyable&); } //继承Uncopyable可以阻止HomeForSale对象被拷贝 class HomeForSale:private Uncopyable { .
3.资源管理
Resource Management # 13.Use objects tomanage resources # 获得资源后立刻放进管理对象,RAII(Resource Acquisition Is Initialization资源获取时机便是初始化时机) 管理对象运用析构函数确保资源被释放 auto_ptr和tr1::shared_ptr两者都在其析构函数内做delete而不是delete[]动作,vector和string几乎总是可以取代动态分配而得的数组,可以使用boost::scoped_array和boost::shared_array类 14.Think carefully about copying behavior in resource-managing classes # 如果复制动作对RAII class 并不合理,考虑禁止复制 复制RAII对象必须一并复制它所管理的资源,常见的RAII class copying行为是:抑制copying,施行引用计数法 15.Provide access to raw resources in resource-managing classes # APIs往往要求访问原始资源,所以每个RAII class应该提供一个取得其所管理之资源的办法 通常通过调用abort结束程序,来阻止异常从析构函数传播出去 class Font{ public: explicit Font(FontHandle fh):f(fh) {} ~Font() { releaseFont(f); } operator FontHandle() const;//隐式转换函数 { return f; } private: FontHandle f; } 16.
4.设计与声明
Designs and Declarations # 18.Make interfaces easy to use correctly and hard to use incorrectly # 好的接口容易被正确使用 ,不容易被误用 阻止误用的办法包括建立新类型、限制类型上的操作,束缚对象值,以及消除客户的资源管理责任 19.Treat class design as type design # Class的设计就是type的设计 标准string和STL窗口都不被设计作为base classed使用,因为它们的析构函数都不带virtual 20.Prefer pass-by-reference-to-const to pass-by-value # 对于内置类型,以及STL的迭代器和函数对象,使用pass-by-value更合适 C++编译器底层中的references往往是以指针方式实现的,意味着真正传递的是指针 21.Don’t try to return a reference when you must return an object # 当必须返回新对象时,就让那个函数返回新对象,如下
5.实现
Implementations # 26.Postpone variable definitions as long as possible # std::string encryptPassword(const std::string& password) { std::string encrypted;//默认构造 encrypted = passwd;//赋值操作 encrypt(encrypted); return encrypted; } 更推荐下面的做法,更高效 std::string encryptPassword(const std::string& password) { std::string encrypted(passwd);//copy构造 encrypt(encrypted); return encrypted; } //1次构造,1次析构,n次赋值 Widget w; for(int i = 0;i < n; ++i) { w = ... } 更推荐上面的做法,更高效 //n次构造,n次析构 for(int i = 0;i < n; ++i) { Widget w; w = .
6.继承与面向对象
Inheritance and Object-Oriented Design # 32.Make sure public inheritance models “is-a” # public inheritance(公开继承)意味"is-a"(是一种)的关系 33.Avoid hideing inherited names # derived classed 内的名称会遮掩base classed内的名称 class Base{ private: int x; public: virtual void mf1() = 0; virtual void mf1(int); void mf3(); void mf3(double); } class Derived : public Base{ public: virtual void mf1(); void mf3(); void mf4(); } Derived d; int x; .