就像你所看到的,上面的代码进行了两次转型,而不是一次。我们要让非 const 的 operator[] 去调用 const 版本的,但是如果在非 const 的 operator[] 的内部,我们只调用 operator[] 而不标明 const ,那么函数将对自己进行递归调用。那将是成千上万次的毫无意义的操作。为了避免无穷递归的出现,我们必须要指明我们要调用的是 const 版本的 operator[] ,但是手头并没有直接的办法。我们可以用 *this 从 TextBlock& 转型到 const TextBlock& 来取代。是的,我们使用了一次转型添加了一个 const !这样我们就进行了两次转型:一次为 *this 添加了 const (于是对于 operator[] 的调用将会正确地选择 const 版本),第二次转型消去了 const operator[] 返回值中的 const 。
添加 const 的那次转型是为了保证转换工作的安全性(从一个非 const 对象转换为一个 const 的),这项工作的关键字是 static_cast 。消去 const 的工作只可以通过 const_cast 来完成,所以在这里我们实际上并没有其他的选择。c 类 static 函数(从技术上讲,我们有。 C 语 言风格的转型在这里也能工作,但是,就像我在第 27 项中所讲的,这一类转型在很多情况下都不是好的选择。如果你对于 static_cast 和 const_cast 还不熟悉,第 27 项中有详细的介绍。)
在众多的示例中,我们最终选择了一个运算符来进行演示,因此上面的语法显得有些古怪。这些代码可能不会赢得任何选美比赛,但是通过以 const 版本的形式实现非 const 版本的 operator[] ,可以避免代码重复,这正是我们所期望的。为达到这一目标而写下看似笨拙的代码,这样做是否值得全看你的选择,但是,以 const 版本的形式来实现非 const 的成员函数——了解这一技术肯定是值得的。
更值得你了解的是按反方向完成上面的工作——通过让 const 版本的函数调用非 const 版本来避免代码重复——一定不要这样做。请记住,一个 const 成员函数保证其对象永远不会更改其逻辑状态,但是一个非 const 的成员函数并没有这一类的保证。如果你在一个 const 函数中调用了一个非 const 函数,曾保证不会被改动的对象就有被修改的风险。这就是为什么说让一个 const 函数调用一个非 const 函数是错误的:对象有可能被修改。实际上,为了使代码能够得到编译,你还需要使用一个 const_cast 来消去 *this 的 const 属性,显然这是不必要的麻烦。上一段中相反的调用次序才是安全的:非 const 成员函数可以对一个对象做任何想做的事情,因此调用一个 const 成员函数不会带来任何风险。这就是为什么 static_cast 在没有与 const 相关的危险的情况下可以正常工作的原因。
就像本项最开始所说的, const 是一个令人赞叹的东西。对于指针和迭代器,以及指针、迭代器和引用所涉及的对象,函数的参数和返回值,局部变量,成员函数来说, const 都是一个强大的伙伴。只要可能就可以使用它。你会对你所做的事情感到高兴的。
需要记住的
1.将一些东西声明为 const 的可以帮助编译器及时发现用法上的错误。 const可被施加于任何作用于内的对象、函数参数、函数返回类型、成员函数本体。
2.编译器严格遵守按位恒定规则,但是你应该在需要时应用逻辑恒定。
3.当 const 和非 const 成员函数的实现在本质上相同时,可以通过使用一个非 const 版本来调用 const版本来避免代码重复
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-62399-6.html
故意来挑挑内部矛盾
够早的啊