设为首页 加入收藏

TOP

Effective C++读书笔记(条款24-29)(三)
2015-07-20 17:17:53 来源: 作者: 【 】 浏览:17
Tags:Effective 读书 笔记 条款 24-29
);{} //缺省实现码什么也没做 ... }; class SpecialWindow:public Window{ public: virtual void blink(){...}; //blink做某些事 ... }; ... typedef std::vector > VPW; VPW winPtrs; ... //容器,内含Window指针,指向所有可能的派生类对象 for(VPW::iterator iter = winPtrs.begin(); iter != winPtrs.end();++iter){ (*iter)->blink(); }


#3.如果转型无可避免,请将它隐藏在函数背后,这样客户调用该函数时,不需要将

转型动作放入它们的代码里,保证了代码的封装性和易维护性。

#4.尽量用C++-style的转型替换旧式转型(构造函数除外),因为
(1).它们很容易在代码中辨别出来,因此简化了“找出类型系统破坏点”的过程。
(2).转型动作分门别类,因此更有利于编译器找出错误的运用。
____________________________________________________________________________________________________________________________________
条款28:若返回 handles 指向对象内部成分,请保证返回值 const 约束大于等于成员函数
#1.References, 指针和迭代器通通都是 handles,用来取得某个对象。
#2.若返回handles指向内部对象,并且成员函数是const,请保证该返回值也是const 。
class Point{
public:
    Point(int x, int y);
    ...
    void setX(int newVal);
    void setY(int newVal);
    ...
};
struct RectData{
    Point ulhc;
    Point lrhc;
};
class Rectangle{
    ...
private:
    std::tr1::shared_ptr
    
      pData;
    Point& upperLeft()const{return pData->ulhc;}
    Point& lowerRight()const{return pData->lrhc;}
    ...
};
Point coord1(0,0);Point coord2(100, 100);
const Rectangle rec(coord1, coord2);

rec.upperLeft().setX(50);
//这里返回的handles可以改变,但与upperLeft const()成员函数的本意是相反的。
//所以应改成:
class Rectangle{
    ...
private:
    ...
    const Point& upperLeft()const{return pData->ulhc;}
    const Point& lowerRight()const{return pData->lrhc;}
    ...
};
//这样就可以在保证读写权的同时禁止涂写权。
    

【本条为个人观点:】
#3.对于返回值为自定义(或系统定义)类型的non-const成员函数,返回内部成员
变量的handles(non-const)表示希望该内部变量是public,而对于返回值为内置
类型的成员变量,则该使用pass-by-valued的getXXX()函数和setXXX(X)来分别
区分读写行为。
例如:
//当upperLeft(),lowerRight()为non-const时:
class Rectangle{
    ...
private:
    ...
    Point& upperLeft(){return pData->ulhc;}
    Point& lowerRight(){return pData->lrhc;}
    ...
};

Point coord1(0,0);Point coord2(100, 100);
Rectangle rec(coord1, coord2);
//我们可以如下这样用函数统一接口设置值和得到值:
rec.upperLeft().setX(50);
int val = rec.lowerRight().getY();
____________________________________________________________________________________________________________________________________
条款29:为”异常安全“而努力是值得的
#1.异常安全函数即使发生异常也不会泄露资源或允许任何数据败坏。
这样的函数区分三种可能的保证:基本型,强烈型,不抛异常性。
(1).基本型:异常抛出后,class一切约束条件满足,程序内事物处于一种有效的状态中。
(2).强烈保证型:异常抛出后,程序状态不改变,函数回到调用前的状态。
(3).不抛异常型:保证不抛出任何异常,对内置类型(int,指针,等)身上的所有操作
都提供nothrow保证。
(任何使用动态内存的东西在无法满足内存需求下,都会抛出bad_alloc异常)

#2.除非调用传统非安全异常安全码,否则应保证异常安全,因为传统非异常安全码
不具备异常安全性,所以任何调用它的代码都不具备异常安全性,因此为其撰写
异常安全码是么有任何意义的。

#3.”强烈保证“往往能够以 copy-and-swap实现出来。
//一个用copy-and-swap的示例:
struct PMImpl{            //PMImpl = PrettyMenu Impl
    std::tr1::shared_ptr bgImage;
    int imageChanges;
};
class PrettyMenu{
    ...
private:
    Mutex mutex;
    std::tr1::shared_ptr
    
      pIml;
};
void PrettyMenu::changeBack(std::istream& imgSrc)
{
    using std::swap;
    Lock ml(&mutex);        //获得mutex的副本数据
    std::tr1::shared_ptr
     
       pNew(new PMImpl(*pImpl)); pNew->bgImage.reset(new Image(imgSrc)); //修改副本 ++pNew->ImageChanges; swap(Impl, pNew); //置换(swap)数据,释放mutex } //,但”强烈保证“ 并非对所有函数都具有可实现或具备实现意义:
     
    
(1).因为如copy-and-swap这样的强烈保证往往会耗费更多的时间和空间,为了
保证更好的效率,应以”基础保证“来替换,这样才更具现实意义。

(2).当函数对”非局部性数据”有影响时,提供强烈保证就很难了。
void someFunc{
    ...     //对local状态做一份副本
    f1();
    f2();
    ...     //将修改后的状态置换过来
}
//假设someFunc对“局部数据”提供
首页 上一页 1 2 3 4 下一页 尾页 3/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇hdu 5014 贪心+位处理 下一篇POJ3169(最短路+差分约束)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·怎样用 Python 写一 (2025-12-27 02:49:19)
·如何学习python数据 (2025-12-27 02:49:16)
·想要自学数据分析, (2025-12-27 02:49:14)
·Java 集合框架 - 菜 (2025-12-27 02:19:36)
·Java集合框架最全详 (2025-12-27 02:19:33)