08-C++ Primer-第2章-开始学习C++-2.4.3-函数-2.5总结

2.4.3用户定义的函数

标准C库提供了140多个预定义的函数,如果其中的函数能满足需求,则应使用它们。但用户经常需要编写自己的函数,尤其是在设计类的时候。无论如何,设计自己的函数很有意思,下面来介绍这一过程。前面已经使用过好几个用户定义的函数,它们都叫main()。每个C++程序都必须有一个main()函数,用户必须对它进行定义。假设需要添加另一个人用户定义的函数。和库函数一样,也可以通过函数名来调用用户定义的函数。对于库函数,在使用之前必须提供其原型,通常把原型放到main()定义之前。但现在您必须提供新函数的源代码。最简单的方法是,将代码放在main()的后面。程序2.5演示了这些元素:

程序2.5    ourfunc.cpp

//ourfunc.cpp--defining your own function

#include<iostream>
void simon(int);

int main()
{
	using namespace std;
	simon(3);     
	cout<<"Pick an integer:";
	int count;
	cin>>count;
	simon(count);
	cout<<"Done!"<<endl;
	return 0;
}

void simon(int n)
{
	using namespace std;
	cout<<"Simon says touch your toes "<<n<<" times."<<endl;
}

main()函数两次调用simom()函数,一次的参数是3,另一次的参数为变量count。在这两次调用之前,用户输入一个整数,用来设置count的值。这个例子没有在cout提示信息中使用换行符。这样将导致用户输入和提示出现在同一行中。下面是运行情况:

1、函数格式

在程序2.5中,simon()函数的定义与main()的定义采用的格式相同。首先,有一个函数头,然和是花括号中的函数体。可以把函数的格式统一为如下的情形:

type functionname(argumentlist)

{

statements

}

注意,定义simon()的源代码位于main()的后面,和C一样(但不同于Pascal),C++不允许将函数定义嵌套在另一个函数定义中。每个函数定义都是独立的,所有函数的创建都是平等的。

2、函数头

在程序2.5中,simon()函数的函数头如下:

void simon(int n)

开头的void表面simon()没有返回值,因此调用simon()不会生成可在main()中将其赋给变量的数字。因此,第一个函数调用方式如下:

simon(3);

由于simon()没有返回值,因此不能这样使用它:

simple=simon(3);

括号中的int n表面,使用simon时,应提供一个int 参数,n是一个新的变量,函数调用时传递的值将被赋给它。因此,下面的函数调用将3赋给simon()函数头中定义的变量n:

simon(3);

当函数体中的cout语句使用n时,将使用函数调用时传递的值。这就是为什么simon(3)在输出中显示3的原因所在。在示例运行中,函数调用simon(count)导致函数显示512,因为这正是赋给count的值。简言而之,simon()的函数头表面,该函数接受一个int 参数,不返回任何值。

下面复习一下main()的函数头:

int main()

开头的int表明,main()返回一个整数值,空括号(可以包含void)表明,main()没有参数,对于有返回值的函数,应使用关键字return来提供返回值,并结束函数,这就是为什么要在main()结尾使用下属语句的原因:

return 0;

这在逻辑上是以指的:main()返回一个int,而程序员要求它返回整数0。但可能会产生疑问,将这个值返回到哪里了呢?毕竟,程序中没有哪个地方可以看出对main()的调用:

squeeze=main();

答案是,可以将计算机操作系统(如UNIXWindows)看作调用程序。因此,main()的返回值并不是返回给程序的其他部分,而是返回给操作系统。很多操作系统都可以使用程序的返回值。例如 ,UNIX外壳脚本和Windows命令行批处理文件都被设计成运行程序,并测试它们的返回值(通常叫做退出值)。通常的约定是,退出值为0则意味着程序运行成行,为非零则意味着存在问题。因此,如果C++程序无法打开文件,可以将它设计为返回一个非零值。然后,便可以设计一个外壳脚本或批处理文件来运行该程序,如果该程序发出指示失败的消息,则采取其他措施。

关键字

关键字是计算机语言中的词汇。本章使用了4C++关键字:intvoidreturndouble。由于这些关键字都是C++专用的,因此不能用作他用。也就是说,不能将return用作变量名,也不能把double用作函数名。不过可以把它们用作名称的一部分,如painter(其中包含int)return_aces。另外,main不是关键字,由于它不是语言的组成部分。然而,它是一个必不可少的函数的名称。可以吧main用作变量名(在一些很神秘的以至于无法在这里介绍的情况中,将main用作变量名会引发错误,由于它在任何情况下都是容易混淆的,因此最好不要这样做)。同样,其他函数名和对象名都不能是关键字。然而,在程序中将同一个名称(比如cout)用作对象名和变量名会吧编译器搞糊涂。也就是说,在不使用cout对象进行输出的函数中,可以将cout用作变量名,但不能在同一个函数中同时将cout用作对象名和变量名。

2.4.4用户定义的有返回值的函数

我们在深一步,编写一个使用返回语句的函数。main()函数已经揭示了有返回值的函数的格式:在函数头中指出返回类型,在函数体结尾处使用return。可以用这种形式为在英国观光的人解决重量问题。在英国,很多浴室都已英石为单位,不像美国以磅或公斤为单位。一英石等于14磅,程序2.6使用一个函数来完成这样的转换。

程序2.6    convert.cpp

//convert.cpp--converts stone to pounds
#include<iostream>
int stonetolb(int);
int main()
{
	using namespace std;
	int stone;    
	cout<<"Enter the weight in stone:";
	cin>>stone;
	int pounds =stonetolb(stone);
	cout<<stone<<" stone =";
	cout<<pounds<<" pounds."<<endl;
	return 0;
}

int stonetolb(int sts)
{
	return 14*sts;
}

下面是该程序的运行情况:


main()中,程序使用cin来给整型变量stone提供一个值。这个值被作为参数传递给stonetolb()函数,在该函数中,这个值被赋给变量sts。然后,stonetolb()用关键字return14*sts返回给main()。这表明return 后面并给一定要跟一个简单的数字。这里通过使用较为复杂的表达式,避免创建一个新变量,将结果赋给该变量,然后将它返回。程序将计算表达式的值(这里为210),并将其返回。如果返回表达式的值很麻烦,可以采用更复杂的方式:

int stonetolb(int sts)

{

int pounds=14*sts;

return pounds;

}

这两个版本的返回的结果相同,但第二个版本更容易理解和修改,因为它将计算和返回分开了。通常,在可以使用一个简单变量的地方,都可以使用一个返回值类型与该常量相同的函数。例如,stonetolb()返回一个int值,这意味着可以以下面的方式使用该函数:

int aunt = stonetolb(20);

int aunts =aunt + stonetolb(10);

cout<<Ferdie weighs stonetolb(16)<< pounds.<<endl;

在上述任何一种情况下,程序都将计算返回值,然后再语句中使用这个值。

这些例子表明,函数原型描述了函数的接口,即函数如何与程序的其他部分交互。参数列表指出了何种信息将被传递个函数,函数类型了返回值的类型。程序员有时将函数比作一个有出入它们的信息所指定的黑盒子,具有黑盒效应。

函数stonetobl()短小、简单,但包含了全部的函数特性,麻雀虽小五脏俱全:

l 有函数头和函数体;;

l 接受一个参数

l 返回一个值;

l 需要一个原型

可以把stonetolb()看作函数设计的标准格式,第七章和第八章将更详细地介绍函数。而本章的内容让读者能够很好地了解函数的工作方式及其愈合与C++匹配。

2.3.5 在多函数程序中使用using编译指令

在程序2.5中,两个函数中都包含下面一条using编译指令:

using namespace std;

这是因为每个函数都使用了cout,因此需要能够访问位于名称空间std中的cout定义。

在程序2.5中,可以采用另一种方法让两个函数都能够访问名称空间std,即将编译指令放在函数的外面,其位于两个函数的前面:

 
  
//ourfunc.cpp--repositioning the using directive#include<iostream>
uisng namespace std;void simon(int);int main(){simon(3); cout<<"Pick an integer:";int count;cin>>count;simon(count);cout<<"Done!"<<endl;return 0;}void simon(int n){cout<<"Simon says touch your toes "<<n<<" times."<<endl;}

当前通行的理念是,只让需要访问名称空间std的函数访问它是更好的选择,例如,在程序2.6中,只有main()函数使用了cout,因此没有必要让函数stonetolb()能够访问名称空间std。因此编译指令using被放在函数main()中,使得只有该函数能够访问名称空间std;

总之,让程序能够访问名称空间std的方法有很多种,下面是其中的4种。

using namespace std;放在函数定义之前,让文件中所有的函数都能够使用名称空间std中所有的元素。

using namespace std;放在特定的函数定义中,让该函数能够使用名称空间std中的所有元素。

在特定的函数中使用类似using std::cout;这样的编译指令,而不是using namespace std;,让该函数能够使用指定的元素,如cout

完全不使用编译指令using,而在需要使用名称空间std中的元素时,使用前缀std::,如下所示:

std::cout<<Im using cout and endl from the std namespace<<std::endl;

命名约定

C++程序员给函数、类和变量命名时,可以有很多种选择。程序员对风格的观点五花八门,这些看法有时就像公共论坛上的圣战。就函数名称而言,程序员有一下选择:

Myfunction( )

myfunction( )

myFunction( )

my_function( )

my_funct( )

选择取决于开发团体、使用的技术或库以及程序员个人的品味和喜好。因此凡是符合第三章将介绍的C++规则的风格都是正确的,都可以根据个人的判断而使用。

撇开语言是否允许不谈,个人的命名风格也是值得注意的——它有助于保持一致性和精确性。精确、让人一目了然的个人命名约定是良好的软件工程的标志,它是整个编程生涯中都会起到很好的作用。

2.5总结

C++程序有一个或多个被称为函数的模块组成。程序从main()函数(全部小写)开始执行,因此该函数必不可少。函数有函数头和函数体组成。函数头指出函数的返回值(如果有的话)的类型和函数期望通过参数传递给它的信息的类型。函数体有一系列位于花括号({})中的C++语言组成。

有多种类型的C++语句,包括下述6种。

n 声明语句:定义函数中使用的变量的名称和类型

n 赋值语句:使用赋值运算符(=)给变量赋值

n 消息语句:将消息发送给对象,激发某种行为。

n 函数调用:执行函数。被调用的函数执行完毕后,程序返回到函数调用语句后面的语句

n 函数原型:声明函数的返回类型、函数接受的参数数量和类型

n 返回语句:将一个值从被调用的函数那里返回到调用函数中

类是用户定义的数据类型规范,它详细描述了如何表示信息以及可对数据执行的操作。对象是根据类的规范创建的实体,就像简单变量是根据数据类型描述创建的实体一样。

C++提供了两个用于处理输入和输出的预定义对象(cincout),它们是istreamostream类的实例,这两个类是在iostream文件中定义的。为ostream类定义的插入运算符(<<)使得将数据插入到输出流成为可能;为istream类定义的抽取运算符(>>)能够从输入流中抽取信息。cincout都是智能对象,能够根据程序上下文自动将信息从一种形式转换为另一种形式。

C++可以使用大量的C库函数。要使用库函数,应当包含提供该函数原型的头文件。

 



猜你喜欢

转载自blog.csdn.net/qq_41200424/article/details/80343410