Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1666086
  • 博文数量: 607
  • 博客积分: 10031
  • 博客等级: 上将
  • 技术积分: 6633
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-30 17:41
文章分类

全部博文(607)

文章存档

2011年(2)

2010年(15)

2009年(58)

2008年(172)

2007年(211)

2006年(149)

我的朋友

分类: C/C++

2007-03-07 15:43:40

假设b是一个const string对象:

class string {
public:
  string(const char *value);        // 具体实现参见条款11
  ~string();                        // 构造函数的注解参见条款m5

  operator char *() const;          // 转换string -> char*;
                                    // 参见条款m5
  ...

private:
  char *data;
};

// 一个执行很快但不正确的实现
inline string::operator char*() const
{ return data; }

这个函数的缺陷在于它返回了一个"句柄"(在本例中,是个指针),而这个句柄所指向的信息本来是应该隐藏在被调用函数所在的string对象的内部。这样,这个句柄就给了调用者自由访问data所指的私有数据的机会。

// 一个执行慢但很安全的实现
inline string::operator char*() const
{
  char *copy = new char[strlen(data) + 1];
  strcpy(copy, data);

  return copy;

}

这个实现很安全,因为它返回的指针所指向的数据只是string对象所指向数据的拷贝;通过函数返回的指针无法修改string对象的值。

当然,安全是要有代价的:这个版本的代码运行起来比前面那个简单版本要慢;并且函数的调用者还要记得delete掉返回的指针。

如果不能忍受这个版本的速度,或者担心内存泄露,可以来一点小小的改动:使函数返回一个指向const char的指针:

class string {
public:
  operator const char *() const;

  ...

};

// 一个既快又安全的实现

inline string::operator const char*() const
{ return data; }


指针并不是返回内部数据句柄的唯一途径。引用也很容易被滥用。下面是一种常见的用法,还是拿string类做例子:

class string {
public:

  ...

  char& operator[](int index) const
  { return data[index]; }

private:
  char *data;
};

string s = "i'm not constant";

s[0] = 'x';               // 正确, s不是const

const string cs = "i'm constant";

cs[0] = 'x';              // 修改了const string,但编译器不会通知

注意string::operator[]是通过引用返回结果的。这意味着函数的调用者得到的是内部数据data[index]的另一个名字,而这个名字可以用来修改const对象的内部数据。这个问题和前面看到的相同,只不过这次的罪魁祸首是引用,而不是指针。

这类问题的通用解决方案和前面关于指针的讨论一样:或者使函数为非const,或者重写函数,使之不返回句柄。











阅读(884) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~