Effective C++读书笔记之尽可能使用const

1) const成员函数
         将const实施于成员函数的目的,是为了确认该成员函数可作用于const对象 身上。这一类成员函数之所以重要,基于两个理由。
         第一,它们使class接口比较 容易被理解。这是因为,得知哪个函数可以改动对象内容而哪个函数不行,很是重 要。
         第二,它们使“操作const对象”成为可能。这对编写高效代码是个关键, 改善C+十程序效率的一个根本办法是以pass勿 reference-to-const方式传递对象,而此技术可行的前提是,我们有const成员函数 可用来处理取得(并经修饰而成)的const对象。
         成员函数如果是const意味什么?这有两个流 行概念:bitwise constness(又称physical constness)和logical constness。 bitwise const阵营的人相信,成员函数只有在不更改对象之任何成员变量(static 除外)时才可以说是const。也就是说它不更改对象内的任何一个bit。这种论点的 好处是很容易侦测违反点:编译器只需寻找成员变量的赋值动作即可。bitwise  constness正是C++对常量性(constness)的定义,因此const成员函数不可以更 改对象内任何non-static成员变量。
        不幸的是许多成员函数虽然不十足具备const性质却能通过bitwise测试。更 具体地说,一个更改了“指针所指物”的成员函数虽然不能算是const,但如果只 有指针(而非其所指物)隶属于对象,那么称此函数为bitwise const不会引发编译 器异议。这导致反直观结果。如何处理这种状况呢。 解决办法很简单:利用C++的一个与const相关的摆动场:mutable(可变的)。 mutable释放掉non-static成员变量的bitwise constness约束。

2) 在const和non-const成员函数中避免重复
         对于“bitwise-constness非我所欲”的问题,mutable是个解决办法,但它不 能解决所有的const相关难题。举个例子,假设TextBlock(和CTextBlock)内 的operator[]不单只是返回一个reference指向某字符,也执行边界检验(bounds  checking)、日记访问信息(logged access info)、甚至可能进行数据完善性检验。 把所有这些同时放进const和non-const operator[]中,导致这样的怪物,然后带来一系列乱七八糟的问题。
   
   
  1. class TextBlock{
  2. public:
  3. ...
  4. const char& operator[] (std::size_t position) const
  5. {
  6. ...
  7. ...
  8. ...
  9. return text[position];
  10. }
  11. const char& operator[] (std::size_t position)
  12. {
  13. ...
  14. ...
  15. ...
  16. return text[position];
  17. }
  18. private:
  19. std::string text;
  20. };
         我们真正该做的是实现operator[]的机能一次并使用它两次。也就是说,必 须令其中一个调用另一个。这促使我们将常量性转除(casting away constness )。本例中的问题,当用 const和non-const成员函数有着实质等价的实现时, 令non-const版本调 const版本可避免代码重复。代码如下:
     
     
  1. class TextBlock{
  2. public:
  3. ...
  4. const char& operator[] (std::size_t position) const
  5. {
  6. ...
  7. ...
  8. ...
  9. return text[position];
  10. }
  11. const char& operator[] (std::size_t position)
  12. {
  13. return const_cast<char&>( static_cast<const TextBlock&> (*this)[position]);
  14. }
  15. ...
  16. };
将operator[]返回值得const转储为*this 加上const 调用 const operator[]。 这里将**this从其原始类型TextBlock&转型为 const  TextBlock&。 使用转型操作为它加上const!所以这里共有两次转型:
第一次用来为*this添加const(这使接下来调用operator[]时得以调用const 版本),
第二次则是从const operator[]的返回值中移除const。
         添加const的那一次转型强迫进行了一次安全转型(将non-const对象转为 const对象),所以我们使用static cast。移除const的那个动作只可以借由 const cast完成,没有其他选择
注意:
         更值得了解的是,反向做法—令const版本调用non-const版本以避免重 复—并不是你该做的事。记住,const成员函数承诺绝不改变其对象的逻辑状态 ( logical state,non-const成员函数却没有这般承诺。如果在const函数内调用 non-const函数,就是冒了这样的风险:你曾经承诺不改动的那个对象被改动了。 这就是为什么“cons七成员函数调用non-cons七成员函数”是一种错误行为:因为 对象有可能因此被改动。实际上若要令这样的代码通过编译,你必须使用一个 const cast将*this身上的const性质解放掉,这是乌云罩顶的清晰前兆。反向调 用(也就是我们先前使用的那个)才是安全的:non-const成员函数本来就可以对 其对象做任何动作,所以在其中调用一个const成员函数并不会带来风险。这就 是为什么本例以static cast作用于*this的原因:这里并不存在const相关危险。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值