effective c++
文章平均质量分 51
beecindy
hi
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
条款51:编写new和delete时需固守常规
很多人没有意识到operator new成员函数会被derived classes继承,那就会出现,有可能base class的operator new被调用用以分配derived class对象。因此derived class的operator new的代码建议:struct Base{ static void* operator new(std::s原创 2010-04-12 09:43:00 · 461 阅读 · 0 评论 -
条款33:避免遮掩继承而来的名称
问题代码:class Base {private: int x;public: virtual void mf1() = 0; // virtual void mf1(int); // overload virtual void mf2(); void mf3(); void mf3(double); // overload ...};class原创 2010-03-15 13:08:00 · 323 阅读 · 0 评论 -
条款35: 考虑virtual函数以外的选择
class GameCharacter {public: virtual int healthValue() const; // return characters health rating; ... // derived classes may redefine this}; 选择方案一原创 2010-03-15 15:22:00 · 387 阅读 · 0 评论 -
条款32:确定你的public继承塑模出is-a关系
class Person {...};class Student: public Person {...};我们从日常的经验知道每一个学生都是一个人,但并不是每一个人都是一个学生。这就是由这个继承体系严格确定的意义。 public inheritance 和 is-a 等价听起来简单,但有时你的直觉会误导你。class Rectangle {...};class原创 2010-03-15 11:47:00 · 350 阅读 · 0 评论 -
条款34:区分接口继承和实现继承
作为一个 class 的设计者class Shape {public: virtual void draw() const = 0;//1 virtual void error(const std::string& msg);//2 int objectID() const;//3 ...}; 1、有的时候你想要 derived classes 只继承一个原创 2010-03-15 13:50:00 · 412 阅读 · 0 评论 -
条款38:通过复合塑膜出has-a或"根据某物实现"
1、has-aclass Address{...};class PhoneNumber{...};class Person{ ...private: std::string name_; Address address_; PhoneNumber voiceNumber_; PhoneNumber faxNumber_;}; Pers原创 2010-03-19 18:31:00 · 473 阅读 · 0 评论 -
条款36:绝对不要重新定义继承而来的non-virtual函数
class b {public: void mf(); ...};class d: public b {public: void mf(); // hides b::mf; see item33 ...}; 如果你在编写 class d 而且你重定义了一个你从 class b 继承到的非虚拟函数mf,d的objects将很可能表现原创 2010-03-19 17:15:00 · 475 阅读 · 0 评论 -
条款37:绝不重新定义继承而来的缺省参数值
问题代码:class Shape{public: enum Color{RED,GREEN,BLUE}; virtual void draw(Color color = RED)const = 0; ...};class Circle:public Shape{public: virtual void draw(Color color = GREEN)c原创 2010-03-19 18:00:00 · 408 阅读 · 0 评论 -
条款13:以对象管理资源
问题代码://没有走到DELETE一部,如中间过程有RETURN语句void f(){ Investment* pInv = creatInvestment(); ... delete pInv;} 解决:智能指针。把资源放入对象内,利用析构函数确保释放。1、资源取得时机便是初始化时机"(Resource Acquisition Is Initializatio原创 2010-01-06 09:00:00 · 317 阅读 · 0 评论 -
条款39:明智而审慎地使用private继承
private继承其实意味着implemented-in-terms-of(根据某物实现出)。如果你写的class Derived以private继承自class Base,你的用意是为了让 Dervived类采用到Base类中的某些特性,而不是因Dervied对象与Base对象存在一些观念上的关系。 关于is-implemented-in-term-of(根据某物来实现原创 2010-03-25 16:52:00 · 475 阅读 · 0 评论 -
条款40:明智而谨慎地使用多重继承
1、多重继承的歧义性问题class BorrowableItem { // something a library lets you borrowpublic: void checkOut(); // check the item out from the library ..};class ElectronicGadget {private: bool c原创 2010-03-25 17:57:00 · 451 阅读 · 0 评论 -
条款41:了解隐式接口和编译期多态
1、显式接口和执行期多态 对于 classes(类),interfaces(接口)是 explicit(显式)的并以 function signatures(函数识别特征)为中心的。polymorphism(多态性)通过 virtual functions(虚拟函数)出现在运行期。class Widget {public: Widget(); virtual ~原创 2010-03-27 12:30:00 · 457 阅读 · 0 评论 -
条款42:了解typename的双重意义
1、两个概念template // print 2nd element invoid print2nd(const C& container) // container;{ // this is not valid C++! if (container.size() >= 2) { //nested dependent name C::const_iterator原创 2010-03-28 14:24:00 · 427 阅读 · 0 评论 -
条款28:避免返回handles指向对象内部成分
1、避免返回对象内部构件的句柄(引用,指针,或迭代器)。这样会提高封装性,帮助const成员函数产生const效果。class Point {// class for representing points public: Point(int x, int y); ... void setX(int newVal); void setY(int原创 2010-03-10 11:12:00 · 377 阅读 · 0 评论 -
条款49:了解new-handler的行为
我们知道new操作符私底下通过调用operator new来实现内存分配的。当operator new无法满足内存申请时,它会不断调用new-handler函数,直到找到足够内存。而客户是通过set_new_handler将自己的new-handler传递给它的。struct Widget{ static std::new_handler set_new_handler( s原创 2010-04-11 10:40:00 · 324 阅读 · 0 评论 -
条款52:写了placement new也要写placement delete
当你在写一个new表达式像这样: Widget* new_widget = new Widget; 共有两个函数被调用:一个是用以分配内存的operator new,一个是Widget的default构造函数.那么假设我们现在遇到的情况是:第一个函数调用成功,第二个函数却抛出异常.按照常理,在步骤一中所分配的内存必须取消,否则就会造成内存原创 2010-04-12 11:09:00 · 571 阅读 · 0 评论 -
条款54:让自己熟悉包括TR1在内的标准程序库
tr1::shared_ptr:引用计数性质的智能指针。注意不能应用循环引用情况 tr1::weak_ptr:不对shared_ptr引用计数进行影响的“弱”指针,可以和shared_ptr搭配使用以解决资源的循环引用问题。当shared_ptr因引用计数为0而被释放时,相关的weak_ptr自动标记为无效。 tr1::function:delegate在C++原创 2010-04-16 11:41:00 · 714 阅读 · 0 评论 -
条款55:让自己熟悉 Boost
Boost有两点被认为是其它组织所不能比拟的。首先,它唯一地与 C++ 标准委员会之间有着紧密和有影响力的关系。Boost是由委员会成员所创建,且现在 Boost成员与委员会成员之间继续保持着许多的交迭。除此之外,Boost的目标之一就是为可能加入到C++标准中的能力但当测试环境。这一切的结果是 14个新加入到 TR1 (看条款 54) 中的库有超过 2/3 以 Bo原创 2010-04-16 11:52:00 · 711 阅读 · 0 评论 -
条款44:将与参数无关的代码抽离templates
问题提出:这个 template(模板)取得一个 type parameter(类型参数)T,但是它还有一个类型为 size_t 的参数——一个 non-type parameter(非类型参数)。template<typename T, // template for n x n matrices ofstd::size_t n> // objects of type T; s原创 2010-04-03 18:58:00 · 498 阅读 · 0 评论 -
条款46:需要类型转换时请为模板定义非成员函数
问题提出:templateclass Rational{public: Rational(const T& numberator = 0, const T& denominator = 1); const T numerator()const; const T denominator()const; ...};templateconst Rational o原创 2010-04-05 17:25:00 · 482 阅读 · 0 评论 -
条款47:请使用traits classes表现类型信息
STL迭代器可分为五类: struct input_iterator_tag{};struct output_iterator_tag{};struct forward_iterator_tag:public input_iterator_tag{};struct bidirectional_iterator_tag:public forward_iterator_tag{};原创 2010-04-05 19:26:00 · 504 阅读 · 0 评论 -
条款43:学习处理模板化基类内的名称
问题提出:templateclass MsgSender{public: ... void sendClear(const MsgInfo& info){ std::string msg; ...//根据info产生信息 Company c; c.sendClearText(msg); } void sendSecret(const原创 2010-04-03 16:33:00 · 371 阅读 · 0 评论 -
条款45:运用成员函数模板接受所有兼容类型
继承体系之间的转换操作:class Top{ ... };class Middle:public Top{...};class Bottom:public Middle{...};Top* top1 = new Middle; //将Middle*转换为Top*Top* top2 = new Bottom; //将Bottom*转换为Top*co原创 2010-04-05 12:59:00 · 422 阅读 · 0 评论 -
条款48:认识template元编
template // general case: the value ofstruct Factorial { // Factorial is n times the value // of Factorial enum { value = n * Factorial::value };};template<> // special case: the value ofs原创 2010-04-05 20:45:00 · 787 阅读 · 0 评论 -
条款6:若不想使用编译器自动生成的函数,就该明确拒绝
你怎么可以复制某些先天独一无二的东西呢?如 认为HomeForSale h3(h1) 或 h1 = h2 对某项任务是不合符情理时,此时,目标是阻止COPYING的发生。方法是将这些函数声明为private,且只有声明即可。同样,可以使用Uncopyable这样的base class,这个class内无成员函数,能避免了对COPYING的调用。class Uncopyable {原创 2009-12-23 17:29:00 · 314 阅读 · 0 评论 -
条款15: 在资源管理类中提供对原始资源的访问
将RAII class对象转换为其所含原始资源,有两个做法:显示转换和隐式转换 显示:std::trl::shared_ptrpInv(createInvestment());int daysHeld(const Investment* pi);int days = daysHeld(pInv);//错误int days = daysHeld(pInv.get());//正原创 2010-02-05 10:34:00 · 451 阅读 · 0 评论 -
条款18: 让接口容易被正确使用,不易被误用
1、好的接口很容易被正确使用,不容易被误用.你应该在你的所有接口中努力达成这些性质.2、"促进正确使用"的办法包括接口的一致性,以及与内置类型的行为兼容.问题代码:class Date{public: Date(int month,int day,int year); ...}; 修改:struct Day{ explicit Day(int dayValue):v原创 2010-02-09 23:17:00 · 375 阅读 · 0 评论 -
条款17:以独立语句将NEWED对象置入智能指针
错误代码:processWidget(std::tr1::shared_ptr(new Widget), priority()); 原因:若编译器最终获得这样的操作序列:1、执行“ new Widget()”2、调用priority3、调用shared_ptr的构造函数但万一对priority的调用导至异常,会发生什么事情?内存泄漏。 正确代码:原创 2010-02-08 18:00:00 · 345 阅读 · 0 评论 -
条款20:宁以pass-by-reference-to-const替换pass-by-value
pass-by-value的问题:1、多次的构造析构,成本高。2、造成对象切割问题 但内置类型、STL的迭代器、函数对象(?),pass-by-value方式往往比较适合。原创 2010-02-28 16:00:00 · 585 阅读 · 1 评论 -
条款21:必须返回对象时,别妄想返回其reference
问题代码://错误inline const rational& operator*(const rational& lhs, const rational& rhs){ rational result(lhs.n * rhs.n, lhs.d * rhs.d); return result;}//极容易内存漏露inline const ratio原创 2010-02-28 16:37:00 · 362 阅读 · 0 评论 -
条款2:尽量以CONST,ENUM,INLINE替换#DEFINE
类中定义常量:static const int numturns = 5;这是声明式而非定义式。若不需取它们的地址,无须提供定义式。定义式如下:const int GamePlayer::NumTurns; 一个class需要常量值,定义如下:enum{NumTurns = 5};int scores[NumTurns]; 关于“形似函数的宏,最好改用i原创 2009-12-20 23:35:00 · 369 阅读 · 0 评论 -
条款3:尽可能使用const
修饰常量const出现在星号左边:const widge* pw = widget const * pwconst_iterator 修饰指针const出现在星号左边:widge * const pwconst std::vector::iterator iter = vec.begin(); 便用const和non-contst成员函数。并避免代码重复的方法原创 2009-12-21 13:46:00 · 325 阅读 · 0 评论 -
条款4:确定对象被使用前已先被初始化
赋值与初始化的区别:赋值操作完成类似伪初始化工作。 构造函数的一个较佳写法是,使用member initialization list。通常效率较高。省下了default构造函数设初值一步。 函数内的static对象称为local static对象,其他static对象称为non-local static对象。对于不同编译单元内的non-local static对象的初始化顺原创 2009-12-21 18:20:00 · 395 阅读 · 0 评论 -
条款5:了解C++默默编写并调用哪些函数
C++处理类时,当它需要时,它会为类声明一个COPY构造函数,一个COPY ASSIGNMENT操作符和一个析构函数。没有构造函数,会声明一个DEFAULT构造函数。 类中成员含有引用变量时,复制拷贝存在问题。原创 2009-12-22 18:40:00 · 394 阅读 · 0 评论 -
条款23:宁以non-member、non-friend替换member函数
主要原因:non-member、non-friend带来的封装性比member函数高。 例如C++的做法:结合了namespace/ header "webbrowser.h" - header for class WebBrowser itself// as well as "core" WebBrowser-related functionalitynamespace We原创 2010-03-02 09:28:00 · 376 阅读 · 0 评论 -
条款24:若所有参数皆需类型转换,请为此采用non-member函数
Rational class:class Rational {pbulic: Rational(int numerator = 0, int denominator = 1); //注意这个构造函数不为explicit int numerator() const; int denominator() const; //两个接口 提供对成员的访问priavte: ..原创 2010-03-03 16:48:00 · 378 阅读 · 0 评论 -
条款14: 在资源管理类中小心copying行为
并非所有的资源都是heap-based,对于这种资源而言,像auto_ptr和tr1::share_ptr这样的智能指针往往不适合作为资源掌管者。这个时候我们需要建立自己的资源管理类。 基础代码://RAII守则class Lock{public: explicit Lock(Mutex* pm):mutexPtr(pm){ lock(mutexPtr)原创 2010-01-21 18:24:00 · 409 阅读 · 0 评论 -
条款7:为多态基类声明VIRTUAL析构函数
当子类对象经由一个父类指针被删除,而父类带着一个non-virtual析构函数,实际执行时通常发生的是子类成分没被销毁。任何CLASS只要带有virtual函数都几乎确定应该也有一个virtual析构函数。标准string及STL容器不含任何virtual,它们当父类时,请注意。 解决方法:class Shape{ public: virtual原创 2009-12-25 12:14:00 · 325 阅读 · 0 评论 -
条款8:别让异常逃离析构函数
析构中出现调用异常一般采用的方法: 一是只要抛出异常就结束程序: DBConn::~DBConn(){ try{ db_.close(); }catch(...){ .... std::abort();//结束程序,可以强制"不明确行为"死掉原创 2009-12-25 12:38:00 · 505 阅读 · 0 评论 -
条款26:尽可能延后变量定义式的出现时间
原代码:std::string encryptPassword(const std::string& password){ using namespace std; string encrypted;//声明过早,如果下面抛出异常,此声明增加负担 if (password.length() < MinimumPasswordLength)原创 2010-03-05 17:49:00 · 392 阅读 · 0 评论
分享