六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 53|回复: 0

条款21: 尽可能使用const

[复制链接]

升级  68.67%

41

主题

41

主题

41

主题

秀才

Rank: 2

积分
153
 楼主| 发表于 2013-1-27 05:31:58 | 显示全部楼层 |阅读模式
防止你做错事的冲动"const"!!
先提下有个陷阱,比如
typedef pC char*
void f1(pC const  p)//好象是反的,记不清了
并不是所希望的char* const //指针常量,而是const char *p //常量指针;
例子好象是这样的吧,可以搜索typedef陷阱关键字。

那么在函数接口中像
class widget { ... };void f1(const widget *pw);      // f1取的是指向                                // widget常量对象的指针void f2(widget const *pw);      // 同f1

都是等同的,都是一个指向常量的指针,


用const就像开头所说,防止许多错事发生,比如
(a * b) = c;      // 对a*b的结果赋值
函数申明就得是
const rational operator*(const rational& lhs, const rational& rhs);


我还以为const也就这样了,但是接下来这个例子可能让你吓一跳,const在重载函数中的运用
class string {public:  ...  // 用于非const对象的operator[]  char& operator[](int position)  { return data[position]; }  // 用于const对象的operator[]  const char& operator[](int position) const  { return data[position]; }private:  char *data;};string s1 = "hello";cout << s1[0];                  // 调用非const                                // string::operator[]const string s2 = "world";cout << s2[0];                  // 调用const                                // string::operator[],这里语意我是这么理解的,既然s2本身是一个const,那么//调用它的值自然也是const

通过重载operator[]并给不同版本不同的返回值,就可以对const和非const string进行不同的处理:

string s = "hello";              // 非const string对象cout << s[0];                    // 正确——读一个                                 // 非const strings[0] = 'x';                      // 正确——写一个                                 // 非const stringconst string cs = "world";       // const string 对象cout << cs[0];                   // 正确——读一个                                 // const stringcs[0] = 'x';                     // 错误!——写一个                                 // const string

还要注意在返回值上上引用类型的,否则cs[0]='x',结果是对一个局域变量赋值

接下来这章中讲了从语义和数据上来区分const函数对成员数据的修改以及mutable关键字,不是很有兴趣,不打算写代码调试

不过最后对const的总结很值得学习,最后自我总结下
const这个关键字从语义上来说不被修改,一个常量值。但是一些语法上的手脚可能会违背这个约定。比如你定义个类,定义了

一个数据A类型转换函数,并且设定成const。接着你用数据类型A定义了一个指针,指向这个类的某个实例。你会发现可以对它

修改了。 其次,还是从语义上来说,一些东西从外表看过去是不能被修改的,但是在内部还是需要修改或者赋一些值,怎么办

呢?只好用mutable关键字,从各种语法来约束它。

对const修改可有这样方法,
在外部,
class string {public:  // 构造函数,使data指向一个  // value所指向的数据的拷贝  string(const char *value);  ...  operator char *() const { return data;}private:  char *data;};const string s = "hello";      // 声明常量对象char *nasty = s;               // 调用 operator char*() const*nasty = 'm';                  // 修改s.data[0]cout << s;                     // 输出"mello"

在内部:
类的一个成员函数中,this指针就好象经过如下的声明:

c * const this;              // 非const成员函数中

const c * const this;        // const成员函数中
但可以通过初始化一个局部变量指针,使之指向this所指的同一个对象来间接实现。然后,就可以通过这个局部指针来访问你

想修改的成员:

size_t string::length() const{  // 定义一个不指向const对象的  // 局部版本的this指针  string * const localthis =    const_cast<string * const>(this);  if (!lengthisvalid) {    localthis->datalength = strlen(data);    localthis->lengthisvalid = true;  }  return datalength;}
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表