函数
函数是一段可重复使用的语句序列,常被设计用来实现某些特定功能,我们已经知道,每个程序都必须有一个main函数,程序从那里开始执行,然而很多时候,一个程序都有多个函数。
你的程序常常会为了做其他事而中断正在做的事,生活中我们也常常这样,比如你现在正在读一本书,突然想起来要打个电话,于是你放个书签在书中,去打了电话,打完之后又回来从书签的地方继续看书。
C++程序的工作方式也是这样,程序在执行语句时,如果遇到函数调用就会转而执行函数中的语句。函数调用告诉CPU中断正在执行的函数,去执行另一个被调用的函数。CPU会在当前执行的位置“添加一个书签”,然后去调用(执行)被调用的函数,当被调用的函数终止时,CPU会返回之前添加书签的点,继续执行。
发起函数调用的函数称为调用函数,被调用的函数称为被调用函数(the function being called is calledfunction)。下面的示例展示了新函数是如何被定义和调用的:
//#include // Visual Studio用户无须注释此行
#include
// doPrint()函数的定义
void doPrint() // doPrint() 在此例中为被调用函数
{
std::cout << "In doPrint()" << std::endl;
}
// main()函数的定义
int main()
{
std::cout << "Starting main()" << std::endl;
doPrint(); // 中断main()函数,调用doPrint()函数
std::cout << "Ending main()" << std::endl;
return 0;
}
程序输出如下:
Starting main() In doPrint() Ending main()
这个程序从main()函数的顶部开始执行,首先执行std::cout << “Starting main()”<< std::endl;输出Startingmain(),然后调用doPrint()函数,此时main()函数暂停执行,CPU跳转到doPrint()函数,然后执行std::cout<< “In doPrint()” << std::endl;打印出IndoPrint(),doPrint()函数终止,main()函数从刚才暂停的地方继续执行,执行std::cout <<“Ending main()” << std::endl;打印出Ending main()。
注意函数调用是通过使用函数名加上圆括号中的参数列表,由于这里我们的函数都没有使用参数,所以圆括号中为空,下节课我们会更详细谈论函数参数,如果忘记添加参数列表,就无法调用函数。
返回值
还记得前面说过,main()函数执行完后将通过返回语句向操作系统返回一个整型值,你写的函数也可以通过在定义中设置其返回值类型,向调用它的函数返回一个值。返回值类型就是在函数名称之前声明的类型。void意味着函数没有返回值,int意味着函数将返回一个整型值。例如:
// void意味着函数无返回值
void returnNothing()
{
// 所以无需有返回语句
}
// int意味着将向调用函数返回一个整型值
int return5()
{
return 5; //返回整型值,所以需要返回语句
}
下面我们来将这两个函数用在程序中:
#include
// void意味着函数无返回值
void returnNothing()
{
// 所以无需有返回语句
}
// int意味着将向调用函数返回一个整型值
int return5()
{
return 5; //返回整型值,所以需要返回语句
}
int main()
{
std::cout << return5() << std::endl; //打印出5
std::cout << return5() + 2 << std::endl; //打印出7
// returnNothing() 函数被调用,但无返回值
returnNothing();
// return5() 函数被调用,但返回值被丢弃
return5();
//此行无法编译,如果想继续必须注释掉这行代码
std::cout << returnNothing();
return 0;
}
第一次函数调用时,return5()被执行并返回值5,然后值5被传递给了cout;第二次函数调用return5()同样返回5,表达式5+2的值为7传递给cout;第三次函数调用returnNothing(),这个函数什么功能也没有并且没有返回值,于是控制权重回main()函数;第四次return5()被执行,返回值为5,但该返回值无处可去,所以被丢弃;第五次returnNothing()返回值为空,将空的返回值传递给cout是非法的,编译器会对此行报错,所以你想编译这个程序的话必须注释掉这一行。
有个问题常被问到,函数可以使用返回语句返回多个值吗?答案是否定的,每个函数只能返回单一的一个值,但是也有办法解决这个问题,后续深入理解函数的部分我们会再提到。
(译者注:可以这么认为,函数执行完毕后,语句中的函数调用部分将被替换为返回值)
回到main()函数
通过上面的学习,你应当已经能够根据已有的概念,掌握main()函数是如何工作的。当程序被执行时,操作系统会首先调用main()函数,执行跳转到main()函数顶部,main()函数中的语句被按顺序执行,执行完毕后将返回给操作系统一个整型值(通常为0),这就是为什么main()函数写作intmain()。
为什么要返回一个值给操作系统呢?这个值是状态码,告诉操作系统或者其他调用它的程序你的程序是否成功执行。通常的共识是,返回0意味着程序成功执行,返回一个正数意味着失败了。
注意C++标准明确规定main()函数必须返回一个int值,即使你不在main()函数中写return0;,编译器也会自作主张的返回0。但是,写上return0;仍然是一个好习惯,一方面明确你的意图,另一方面也与其他函数保持一致(让你不会忘记为其他函数写上返回值)。
现在你也可以在代码的最后写main()函数,我们会在《1.7前向声明》讨论这个问题。
函数的重复使用
同一函数可以被多次调用,如果某个功能需要多次使用,这一点就非常有用了。例如:
//#include // Visual Studio用户无需注释掉此行
#include
// getValueFromUser函数从用户读取一个输入并返回给调用函数
int getValueFromUser()
{
std::cout << "Enter an integer: ";
int a;
std::cin >> a;
return a;
}
int main()
{
int x = getValueFromUser(); // 第一次调用
int y = getValueFromUser(); // 第二次调用
std::cout << x << " + " << y << " = " << x + y << std::endl;
return 0;
}
程序输出如下(假设两次分别输入5、7):
Enter an integer: 5 Enter an integer: 7 5 + 7 = 12
在这个例子中,main()函数被中断两次(调用getValueFromUser()两次),两次读取的数据分别传递给了x和y。
注意main()函数不是唯一能够调用其它函数的函数,任何函数都能够调用其他函数。
//#include // Visual Studio用户无需注释掉此行
#include
void printA()
{
std::cout << "A" << std::endl;
}
void printB()
{
std::cout << "B" << std::endl;
}
// 函数printAB() 调用了printA()和printB()
void printAB()
{
printA();
printB();
}
int main()
{
std::cout << "Starting main()" << std::endl;
printAB();
std::cout << "Ending main()" << std::endl;
return 0;
}
程序输出如下:
Starting main() A B Ending main()
嵌套函数
C++中不能再一个函数中再定义另一个函数(称为嵌套),例如下面的程序就是非法的:
#include
int main()
{
int foo() // 该函数嵌套在main()中,不合法
{
std::cout << "foo!";
return 0;
}
foo();
return 0;
}
上述程序应当更改为:
#include
int foo()
{
std::cout << "foo!";
return 0;
}
int main()
{
foo();
return 0;
}
转载请参看关于博客页面相关要求。