• 网络学院
  • IT资讯
  • 操作系统
  • 网络技术
  • 软件应用
  • 办公软件
  • 编程技术
  • 网站架设
  • 数据库类
  • 平面设计
  • 多媒体类
  • 游戏资讯
  • 教学论文
  • 认证考试
C++箴言:只要可能就用const
  站点:
  • 首 页
  • 最新软件
  • 文章教程
  • 国内软件
  • 国外软件
  • 绿色软件
  • 源码下载
  • 字体下载
C++箴言:只要可能就用const
软件发布 C++箴言:只要可能就用const
网络软件 系统工具 应用软件 联络聊天 图形图像 多媒体类 行业软件 游戏娱乐 编程开发 安全相关 教育教学 数码软件 绿软下载
热门软件: QQ 瑞星 pplive e话通 木马克星 千千静听 office2000 五笔字根 Photoshop 视频分割
返回文章教程首页 >> 编程技术 >> C/C++教程 >> C++箴言:只要可能就用const

C++箴言:只要可能就用const

添加时间: 2006-2-12 8:49:26  作者: C++教程  阅读次数:2833   来源: http://www.d9soft.com

       
  让我们为哲学留一点时间。看看一个成员函数是 const 意味着什么?有两个主要的概念:二进制位常量性(bitwise constness)(也称为物理常量性(physical constness))和逻辑常量性(logical constness)。

  二进制位 const 派别坚持认为,一个成员函数,当且仅当它不能改变对象的任何数据成员(static 成员除外),也就是说不能改变对象内的任何二进制位,则这个成员函数就是 const。二进制位常量性的一个好处是比较容易监测违例:编译器只需要寻找对数据成员的赋值。实际上,二进制位常量性就是 C++ 对常量性的定义,一个 const 成员函数不被允许改变调用它的对象的任何 non-static 数据成员。

  不幸的事,很多成员函数并不能完全通过二进制位常量性的检验。特别是,一个经常改变一个指针指向的内容的成员函数。除非这个指针在这个对象中,否则这个函数就是二进制位 const 的,编译器也不会提出异议。例如,假设我们有一个类似 TextBlock 的类,因为它需要与一个不知 string 为何物的 C API 打交道,所以它需要将它的数据存储为 char* 而不是 string。

  

  class CTextBlock {

   public:

    ...

    char& operator[](std::size_t position) const // inappropriate (but bitwise

  { return pText[position]; } // const) declaration of

    // operator[]

   private:

    char *pText;

  };

  尽管 operator[] 返回对象内部数据的引用,这个类还是(不适当地)将它声明为 const 成员函数(Item 28 将谈论一个深入的主题)。先将它放到一边,看看 operator[] 的实现,它并没有使用任何手段改变 pText。结果,编译器愉快地生成了 operator[] 的代码,因为对所有编译器而言,它都是二进制位 const 的,但是我们看看会发生什么:

  

  const CTextBlock cctb("Hello"); // declare constant object

  

  char *pc = &cctb[0]; // call the const operator[] to get a

  // pointer to cctb’s data

  

  *pc = ’J’; // cctb now has the value "Jello"

  这里确实出了问题,你用一个确定的值创建一个常量对象,然后你只是用它调用了 const 成员函数,但是你改变了它的值! 这就引出了逻辑常量性的概念。这一理论的信徒认为:一个 const 成员函数被调用的时候可能会改变对象中的一些二进制位,但是只能用客户无法感觉到的方法。例如,你的 CTextBlock 类在需要的时候可以储存文字块的长度:

  

  class CTextBlock {

   public:

    ..

    std::size_t length() const;

  

   private:

    char *pText;

    std::size_t textLength; // last calculated length of textblock

    bool lengthIsValid; // whether length is currently valid

  };

  

  std::size_t CTextBlock::length() const

  {

   if (!lengthIsValid) {

    textLength = std::strlen(pText); // error! can’t assign to textLength

    lengthIsValid = true; // and lengthIsValid in a const

   } // member function

   return textLength;

  }

  length 的实现当然不是二进制位 const 的—— textLength 和 lengthIsValid 都可能会被改变——但是它还是被看作对 const CTextBlock 对象有效。但编译器不同意,它还是坚持二进制位常量性,怎么办呢?

  解决方法很简单:利用以关键字 mutable 为表现形式的 C++ 的 const-related 的灵活空间。mutable 将 non-static 数据成员从二进制位常量性的约束中解放出来:

  

  class CTextBlock {

   public:

    ...

    std::size_t length() const;

  

   private:

    char *pText;

    mutable std::size_t textLength; // these data members may

    mutable bool lengthIsValid; // always be modified, even in

  }; // const member functions

  

  std::size_t CTextBlock::length() const

  {

   if (!lengthIsValid) {

    textLength = std::strlen(pText); // now fine

    lengthIsValid = true; // also fine

   }

   return textLength;

  }
  避免 const 和 non-const 成员函数的重复

  mutable 对于解决二进制位常量性不太合我的心意的问题是一个不错的解决方案,但它不能解决全部的 const-related 难题。例如,假设 TextBlock(包括 CTextBlock)中的 operator[] 不仅要返回一个适当的字符的引用,它还要进行边界检查,记录访问信息,甚至数据完整性确认,将这些功能加入到 const 和 non-const 的 operator[] 函数中,使它们变成如下这样的庞然大物:

  

  class TextBlock {

   public:

    ..

    const char& operator[](std::size_t position) const

    {

     ... // do bounds checking

     ... // log access data

     ... // verify data integrity

     return text[position];

    }

    char& operator[](std::size_t position)

    {

     ... // do bounds checking

     ... // log access data

     ... // verify data integrity

     return text[position];

    }

   private:

    std::string text;

  };

  哎呀!你是说重复代码?还有随之而来的额外的编译时间,维护成本以及代码膨胀等令人头痛的事情吗?当然,也可以将边界检查等全部代码转移到一个单独的成员函数(当然是私有的)中,并让两个版本的 operator[] 来调用它,但是,你还是要重复写出调用那个函数和返回语句的代码。

  怎样才能只实现一次 operator[] 功能,又可以使用两次呢?你可以用一个版本的 operator[] 去调用另一个版本。并通过强制转型去掉常量性。

  作为一个通用规则,强制转型是一个非常坏的主意,我将投入整个一个 Item 来告诉你不要使用它,但是重复代码也不是什么好事。在当前情况下,const 版本的 operator[] 所做的事也正是 non-const 版本所做的,仅有的不同是它有一个 const 返回类型。在这种情况下,通过转型去掉返回类型的常量性是安全的,因为,无论谁调用 non-const operator[],首要条件是有一个 non-const 对象。否则,他不可能调用一个 non-const 函数。所以,即使需要一个强制转型,让 non-const operator[] 调用 const 版本以避免重复代码的方法也是安全的。代码如下,随后的解释可能会让你对它的理解更加清晰:

  

  class TextBlock {

   public:

    ...

    const char& operator[](std::size_t position) const // same as before

    {

     ...

     ...

     ...

     return text[position];

    }

    char& operator[](std::size_t position) // now just calls const op[]

    {

     return

     const_cast( // cast away const on

     // op[]’s return type;

     static_cast(*this) // add const to *this’s type;

C++箴言:只要可能就用const (2) 第 [1] [2] [3]  下一页

 

上下文章:

 

上一篇文章: C++中的struct专题研究 下一篇文章: C++箴言:资源管理类的拷贝行为

相关文章:

  • 微软可能采取降价行动 回应黑屏
  • 美博客列出11家可能倒闭的互联网公司
  • 手机功能接近电脑受病毒袭击可能性大增
  • 10项有可能导致安全问题的行为
  • 中国IP地址告急:新网民两年后可能无法上网

相关软件:

  • GIF Construction Set Pro V3.0a.24
  • PNG MNG Construction Set V2.0.46a

 

快速导航

  • 网络学院
  • 精品汇聚
  • 字体下载
  • 教程下载
  • ASP源码
  • PHP源码
  • Net源码
  • JSP 源码

编程技术分类导航

  • ASP & ASP.NET教程
  • PHP教程
  • JSP教程
  • C/C++教程
  • VB & VB.NET教程
  • VC教程
  • Delphi教程
  • BCB教程
  • VFP教程
  • PB教程
  • JAVA教程
  • XML教程
  • C#教程
  • CGI教程

本类经典文章推荐

  • 使用C++ TR1 生成随机数
  • C/C++作用域引申出的编码规范
  • 程序宝典:C++学习感想
  • C语言:黑客学员必修课(一)
  • C语言:黑客学员必修课(二)
  • 使用多线程实现数据实时采集
  • C++编程中的四个调试小技巧
  • C语言程序设计基础之联合
  • 学C++不得不看的一篇文章
  • C,曾经的程序员梦

C/C++教程阅读排行

  • 学C++不得不看的一篇文章
  • 水滴石穿C语言之可变参数问题
  • C语言:黑客学员必修课(一)
  • 我的Visual C++入门之路
  • 程序宝典:C++学习感想
  • C++中的struct专题研究
  • 初学者学习C++的50条忠告
  • C++箴言:只要可能就用const
  • C++编程中的四个调试小技巧
  • 强大的语言——C入门

编程技术阅读总排行

  • VB入门教程之一
  • Java连接数据库实例
  • VC++之List Box/Check List Box控...
  • 第二章 PowerBuilder 入门之创建新...
  • VC++ List Ctrl控件
  • 第一章 什么是PowerBuilder
  • VC++ Combo Box/Combo Box Ex控件
  • 学C++不得不看的一篇文章
  • VB入门教程之二
  • VC++之Button控件

广告位置

字母检索 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 回到顶部

关于我们 | 版权声明 | 免责条款 | 广告联系 | 软件发布 | 下载帮助 | 下载排行 | 网站地图 | 特别鸣谢 | 友情连接

copyright; 2005-2008 D9soft.com 第九软件网 版权所有