首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java


Special Considerations in the Use of Functions

使用函数时要特别考虑的问题

现代的编程语言,如C++JavaVisual Basic等,都同时支持函数和过程。函数是指有返回值的子程序;过程是指没有返回值的子程序。在C++ 中,通常把所有子程序都称为“函数”;然而,那些返回值类型为void的函数在语义上其实就是过程。函数与过程的区别更多的是语义的区别,而不是语法的区别,你还是要以语义为准。

When to Use a Function and When to Use a Procedure

什么时候使用函数,什么时候使用过程

语言纯化论者们认为,一个函数应该只有一个返回值,就像数学函数一样。这意味着函数只能接受仅用于输入的参数,并只通过函数本身返回一项结果。函数永远应该以它所返回的值来命名,就像sin()CustomerID()ScreenHeight()一样。在另一方面,过程则可以根据所需,接受任意数量的输入、修改和输出参数。

一种常用的编程实践是让函数像过程一样执行并返回状态值。逻辑上,这种东西的的工作方式和过程一样,但是由于具有返回值,它又确实是一个函数。举例来说,你可能有一个名为FormatOutput()的函数,它在类似下面这样的语句里用到了一个report对象:

if ( report.FormatOutput( formattedReport ) = Success ) then ...

在这个例子中,report.FormatOutput()的工作方式就像是过程,因为它有一个输出参数formattedReport,但是因为它有返回值,所以从技术角度来看它又是一个函数。这样使用函数是否正确呢?为支持这种用法 ,你可能保证了该函数的返回值与函数的主要目标——格式化输出——无关,也与函数的名字report.Format­Output()无关。在这种意义下,尽管从技术角度来看它是个函数,但执行起来却更像是一个过程。如果能够统一地使用这种技术,用返回值来表示过程执行成功与否倒也不会让人感到困惑。

代替它的一种方法,就是写一个用状态变量做为显式参数的过程,如下面这段代码所示:

report.FormatOutput( formattedReport, outputStatus )

if ( outputStatus = Success ) then ...

我更喜欢使用第二种编码风格,倒不是因为我对函数和过程之间的分别特别敏感,而是因为这样做可以把对子程序的调用和对状态值的判断清楚地分开。把对子程序的调用和对状态值的判断写在一行代码中,增加了该条语句的密度,也相应地增加了其复杂度。下面这种使用函数的方式也是很好的:

outputStatus = report.FormatOutput( formattedReport )

if ( outputStatus = Success ) then ...

简而言之,如果一个子程序的主要用途就是返回由其名字所指明的返回值,那么就应该使用函数,否则就应该使用过程。

Setting the Functions Return Value

设置函数的返回值

使用函数时总存在返回不正确的返回值的风险。当函数内有多条可能的执行路径,而其中一条执行路径没有设置返回值时,这一错误就出现了。为了减少这一风险,请按照下面给出的建议来做:

检查所有可能的返回路径  在编写函数时,请在脑海里执行每一条执行路径,确保在所有可能的情况下该函数都会返回值。在函数开头用一个默认值来初始化返回值是个很好的做法——这种方法能够在未正确地设置返回值时提供一张保险网

不要返回指向局部数据的引用或指针  一旦子程序执行结束,其局部数据就都出了作用域,那么任何指向局部数据的引用或指针也随之失效。如果一个对象需要返回有关其内部数据的信息,那就应该把这些信息保存为类的数据成员。然后,它还应该提供可以返回这些数据成员的访问器子程序,而不是返回对局部数据的引用或者指针。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论