正文

只要可能就用const2005-11-13 10:14:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/wondgergis/6798.html

分享到:

关键字 const
                  非常多才多艺。在类的外部,你可以将它用于全局常量或命名空间常量,就像那些在文件、函数或模块范围内被声明为 static
                  的对象。在类的内部,你可以将它用于 static 和 non-static 数据成员上。对于指针,你可以指定这个指针本身是
                  const,或者它所指向的数据是 const,或者两者都是,或者都不是。

                    char greeting[] = "Hello";

                    

                    char *p = greeting; // non-const pointer,

                    // non-const data

                    

                    const char *p = greeting; // non-const pointer,

                    // const data

                    

                    char * const p = greeting; // const pointer,

                    // non-const data

                    

                    const char * const p = greeting; // const pointer,

                    // const data

                    这样的语法本身其实并不像表面上那样反复无常。如果 const 出现在 * 左边,则指针指向的内容为常量;如果 const
                  出现在 * 右边,则指针自身为常量;如果 const 出现在 * 两边,则两者都为常量。

                    当指针指向的内容为常量时,一些人将 const 放在类型之前,另一些人将 const 放在类型之后 *
                  之前。两者在意义上并没有区别,所以,如下两个函数具有相同的参数类型:

                    

                    void f1(const Widget *pw); // f1 takes a pointer to a

                    // constant Widget object

                    

                    void f2(Widget const *pw); // so does f2

                    因为它们都存在于实际的代码中,你应该习惯于这两种形式。

                    STL iterators 以指针为原型,所以一个 iterator 在行为上非常类似于一个 T* 指针。声明一个
                  iterator 为 const 就类似于声明一个指针为 const(也就是说声明一个 T* const 指针):不能将
                  iterator 指向另外一件不同的东西,但是它所指向的东西本身可以变化。如果你要一个 iterator
                  指向一个不能变化的东西(也就是 const T* 的 STL 对等物),你应该用 const_iterator:

                    

                    std::vector vec;

                    ...

                    const std::vector::iterator iter = // iter acts like a T*
                  const

                    

                    vec.begin();

                    

                    *iter = 10; // OK, changes what iter points to

                    

                    ++iter; // error! iter is const

                    

                    std::vector::const_iterator cIter = //cIter acts like a
                  const T*

                    

                    vec.begin();

                    

                    *cIter = 10; // error! *cIter is const

                    

                    ++cIter; // fine, changes cIter

                    对 const 最强有力的用法来自于它在函数声明中的应用。在一个函数声明中,const
                  既可以用在函数返回值上,也可以用在个别的参数上,对于成员函数,还可以用于整个函数。

                    一个函数返回一个常量,常常可以在不放弃安全和效率的前提下尽可能减少客户的错误造成的影响。例如,考虑在 Item 24
                  中考察的 rational 成员 operator* 的声明:

                    

                    class Rational { ... };

                    

                    const Rational operator*(const Rational& lhs, const
                  Rational& rhs);

                    很多第一次看到这些的人会不以为然。为什么 operator* 的结果应该是一个 const
                  对象?因为如果它不是,客户就可以犯下如此暴行:

                    

                    Rational a, b, c;

                    ...

                    (a * b) = c; // invoke operator= on the

                    // result of a*b!

                    我不知道为什么一些程序员要为两个数的乘积赋值,但是我知道很多程序员这样做也并非不称职。所有这些可能来自一个简单的输入错误(要求这个类型能够隐式转型到
                  bool):

                    

                    if (a * b = c) ... // oops, meant to do a comparison!

                    如果 a 和 b
                  是内建类型,这样的代码显而易见是非法的。一个好的用户自定义类型的特点就是要避免与内建类型毫无理由的不和谐,而且对我来说允许给两个数的乘积赋值看上去正是毫无理由的。将
                  operator* 的返回值声明为 const 就可以避免这一点,这就是我们要这样做的理由。

                    关于 const 参数没什么特别新鲜之处——它们的行为就像局部的 const
                  对象,而且无论何时,只要你能,你就应该这样使用。除非你需要改变一个参数或本地对象的能力,否则,确认将它声明为
                  const。它只需要你键入六个字符,就能将你从我们刚刚看到的这个恼人的错误中拯救出来:“我想键入‘==’,但我意外地键入了‘=’”。


                    const 成员函数

                    成员函数被声明为 const 的目的是确信这个函数可能会被 const
                  对象调用。因为两个原因,这样的成员函数非常重要。首先,它使一个类的接口更容易被理解。知道哪个函数可以改变对象而哪个不可以是很重要的。第二,它们可以和
                  const 对象一起工作。书写高效代码有一个很重要的方面,就像 Item 20 所解释的,提升一个 C++
                  程序的性能的基本方法就是就是传递一个对象的引用给一个 const 参数。这个技术只有在 const 候选对象有 const
                  成员函数可操作时才是可用的。

                    很多人没有注意到这样的事实,即成员函数只有常量性不同时是可以被重载的,这是 C++
                  的一个重要特性。考虑一个代表文字块的类:

                    

                    class TextBlock {

                    

                     public:

                      ...

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

                      { return text[position]; } // const objects

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

                      { return text[position]; } // non-const objects

                     private:

                      std::string text;

                    };

                    

                    TextBlock 的 operator[]s 可能会这样使用:

                    

                    TextBlock tb("Hello");

                    

                    std::cout << tb[0]; // calls non-const

                    // TextBlock::operator[]

                    

                    const TextBlock ctb("World");

                    

                    std::cout << ctb[0]; // calls const TextBlock::operator[]

阅读(2888) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册