在程序中隐藏数据有什么好处?一方面,如果“完全”隐藏数据,什么都不会更改数据,并且程序的状态永远不会更改,由此,这个程序几乎是没有用的了。另一方面,允许程序中的每个元素自由访问数据很难确定是谁改变了什么。因此,当出现伪值时,你不知道该去哪里找,也不知道该怪谁。也就是说,调试程序变得更加困难。
因此,问题就变成了一个平衡问题:在仍然存在访问的情况下,尽可能多地限制对数据的访问,让那些需要访问数据的程序元素拥有这种访问权。限制对数据的访问称为封装。考虑到封装是可取的,我们有哪些选项来限制对数据的访问呢?令人惊讶的是,我们有很多选择。这些选项中的大多数都基于范围的概念。数据对象访问数据的范围是指其在程序中的可见性和生存期。这个通过示例讨论时,对范围的理解将变得清晰。
最严格的范围级别可能是语句块范围级别。看看下面的代码片段:
注意名为temp的变量是如何在if语句块中定义的。从程序的角度来看,当然,temp一经定义就存在了。下一条语句是将x乘以100,把结果赋值到temp中。到目前为止,尚未对存储在temp中的结果进行任何处理。让我们写完这个程序,以便看到语句块作用域是如何工作的。
代码清单7-1.Statement Block Scope Program
如果尝试编译并运行此代码,则编译器将发出以下错误消息:
LocalScopeProgram.cpp:In function'void loop()':
LocalScopeProgram:22:error:'temp'was not declared in this scope
有什么问题?正如错误消息所指出的,第22行是有问题的,即以下语句:
Serial.println(temp);
错误消息告诉你temp“未在此范围内声明”。换句话说,temp“超出范围”。
问题是你已经将temp定义为具有语句块范围。语句块范围表示数据项从其定义点到其所在语句块内是有效范围。这意味着,从定义的角度来看,temp“存在”或“可用” 于if语句块。到达if语句的右大括号后,temp将从符号表失效,不再存在它“超出范围”。图7-1显示了temp语句块的作用范围。
(www.xing528.com)
图7-1 变量语句块作用范围
在图7-1中,阴影区域定义了变量temp,其作用范围为if语句块中。变量temp只能在阴影区域内的任何地方使用,因为它在这个范围内是可见的。然而,阴影区域以外的任何地方,变量temp是不存在的。在图7-1中的共享区域之外,变量temp不再存在于符号表中,它超出范围,它是不可见的,它是死的。
具有局部作用域的变量从其定义点到该区域结尾都具有存在周期和可见性。图7-2中阴影部分说明了变量x的局部范围。
图7-2 变量局部作用域
具有局部作用域的变量的可见性和寿命从其定义点延伸到定义它的函数的右大括号。在图7-2中,变量x的范围从其定义到loop()函数的右大括号。这意味着图7-2可以访问变量x,而阴影区域之外的任何东西都不知道x。
局部作用域变量在C程序中非常常见。局部范围提供了某种程度的封装,但没有限制到使变量变成无用的程度。语句块范围也是如此。正如你在第6章中所了解的,函数是面向任务的代码片段和局部变量协同工作以解决特定任务。当它们的工作完成后,即函数体内代码之外程序的其余部分而言,该函数中的变量不再存在。
如果移动x的定义,如下面的代码片段所示,会发生什么?
将x的定义移到函数的底部,我们还删除了有问题的print语句,因此前面使用清单7-1看到的错误消失了。当你尝试编译清单7-1的这个变量时,编译器会发出以下错误消息:
LocalScopeProgram.cpp:In function'void loop()':
LocalScopeProgram:17:error:'x'was not declared in this scope
出了什么问题?问题是,变量x只有在loop()函数的底部定义后才能进入作用域。但是,程序代码却在定义x之前尝试访问x。这是大多数程序员将使用的数据定义放在函数中的一个原因。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。