1.4函数与返回值初探

函数

函数是一段可重复使用的语句序列,常被设计用来实现某些特定功能,我们已经知道,每个程序都必须有一个main函数,程序从那里开始执行,然而很多时候,一个程序都有多个函数。

你的程序常常会为了做其他事而中断正在做的事,生活中我们也常常这样,比如你现在正在读一本书,突然想起来要打个电话,于是你放个书签在书中,去打了电话,打完之后又回来从书签的地方继续看书。

C++程序的工作方式也是这样,程序在执行语句时,如果遇到函数调用就会转而执行函数中的语句。函数调用告诉CPU中断正在执行的函数,去执行另一个被调用的函数。CPU会在当前执行的位置“添加一个书签”,然后去调用(执行)被调用的函数,当被调用的函数终止时,CPU会返回之前添加书签的点,继续执行。

发起函数调用的函数称为调用函数,被调用的函数称为被调用函数(the function being called is called function)。下面的示例展示了新函数是如何被定义和调用的:

//#include <stdafx.h> // Visual Studio用户无须注释此行
#include <iostream>

// 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;输出Starting main(),然后调用doPrint()函数,此时main()函数暂停执行,CPU跳转到doPrint()函数,然后执行std::cout << “In doPrint()” << std::endl;打印出In doPrint(),doPrint()函数终止,main()函数从刚才暂停的地方继续执行,执行std::cout << “Ending main()” << std::endl;打印出Ending main()。

注意函数调用是通过使用函数名加上圆括号中的参数列表,由于这里我们的函数都没有使用参数,所以圆括号中为空,下节课我们会更详细谈论函数参数,如果忘记添加参数列表,就无法调用函数。

返回值

还记得前面说过,main()函数执行完后将通过返回语句向操作系统返回一个整型值,你写的函数也可以通过在定义中设置其返回值类型,向调用它的函数返回一个值。返回值类型就是在函数名称之前声明的类型。void意味着函数没有返回值,int意味着函数将返回一个整型值。例如:

// void意味着函数无返回值
void returnNothing()
{
    // 所以无需有返回语句
}

// int意味着将向调用函数返回一个整型值
int return5()
{
    return 5; //返回整型值,所以需要返回语句
}

下面我们来将这两个函数用在程序中:

#include <iostream>

// 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()函数写作int main()。

为什么要返回一个值给操作系统呢?这个值是状态码,告诉操作系统或者其他调用它的程序你的程序是否成功执行。通常的共识是,返回0意味着程序成功执行,返回一个正数意味着失败了。

注意C++标准明确规定main()函数必须返回一个int值,即使你不在main()函数中写return 0;,编译器也会自作主张的返回0。但是,写上return 0;仍然是一个好习惯,一方面明确你的意图,另一方面也与其他函数保持一致(让你不会忘记为其他函数写上返回值)。

现在你也可以在代码的最后写main()函数,我们会在《1.7前向声明》讨论这个问题。

函数的重复使用

同一函数可以被多次调用,如果某个功能需要多次使用,这一点就非常有用了。例如:

//#include <stdafx.h> // Visual Studio用户无需注释掉此行
#include <iostream>

// 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 <stdafx.h> // Visual Studio用户无需注释掉此行
#include <iostream>

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 <iostream>

int main()
{
    int foo() // 该函数嵌套在main()中,不合法
    {
        std::cout << "foo!";
        return 0;
    }
    foo();
    return 0;
}

上述程序应当更改为:

#include <iostream>

int foo()
{
    std::cout << "foo!";
    return 0;
}

int main()
{
    foo();
    return 0;
}

转载请参看关于博客页面相关要求。

发表评论

电子邮件地址不会被公开。