mylogo

退役程序员的茶室 RetiredCoder.cn

← 返回上一页

C++编程基础: 10. 函数

2025-04-14 05:02:01

本系列文章是配合我发布的《C++编程基础》系列视频教程的知识点总结和补充。这一节我们来讲讲函数。

用程序来实现一个项目时往往会有很长的代码,使用函数将实现某个功能的相关代码组织起来,可以帮助我们很好的梳理代码结构,提高程序的可读性、简化程序,也便于对程序改进升级。

函数的声明

在C++里,不像Java,函数的实现要在被调用之前,如果写在了程序调用的后面,编译无法通过,因此需要在前面声明函数的原型。

声明一个函数时,首先是返回值的类型,如果没有返回值,用void代替。接着是自定义一个函数名,跟着一对小括号,里面包含参数的序列,每个参数之间以逗号分隔,如果参数有默认值,可以在声明时设定。声明时括号后面要有分号。 

void printSeparateLine();
string uppercase_A(string str);

函数的定义

函数的定义也就是对函数的具体实现,这时具体实现的代码要在小括号后面用大括号括起,如果这个函数有返回值,函数定义里要有最后会被执行的return语句,即关键字return后面跟着和声明的返回值数据类型一致的数据。如果函数没有返回值,应在返回值数据类型的位置写关键字void来替代,函数内无需包含return语句。

void printSeparateLine(){    
    std::cout<<"--------------------"<<std::endl;
}
string uppercase_A(string str){
    for(int i=0;i<str.length();i++){        
        if(str[i]=='a'){
            str[i]='A';
        }
    }
    return str;
}

在函数中不能包含另一个函数定义,但是它可以调用其他的函数,也可以自己调用自己,即可以实现递归。

形参和实参

在声明、定义中括在函数名后面小括号里的这些参数叫做形参,在程序中调用函数时需要提供实参。

例如在程序里调用uppercase_A时:

str_new = uppercase_A(str_old);

其中str_old是一个对象实例,作为一个实参传递给了uppercase_A这个函数。

函数的重载

有些时候一些函数名称和返回值类型均相同,但需要传递的参数个数或类型可以不同,称之为函数的重载。

例如,声明两个都叫做printSeparateLine的函数:

void printSeparateLine();
void printSeparateLine(int l, char c);

具体实现:

void printSeparateLine(){
    std::cout<<"--------------------"<<std::endl;
}

void printSeparateLine(int l, char c){
    for(int i=0;i<l;i++){
        if(i==l-1){
            std::cout<<c<<std::endl;
        }else{
            std::cout<<c;
        }
    }
}

程序中的调用:

printSeparateLine();
printSeparateLine(20,'*');

为函数参数声明默认值

声明时可以为参数提供默认值,有默认值的参数即成为了可选参数,调用时可以省略相应参数,例如下面的例子中,在声明函数的原型时,将函数printSeparateLine的第二个字符类型的参数默认值设为了’-’:

void printSeparateLine(int l, char c='-');

程序中的调用,可以省略提供第二个参数:

printSeparateLine(20);

内联函数

当程序执行到一个函数而要去调用它时,要暂停手里的工作先去另一个地方处理函数的具体操作,之后再回来继续工作,虽然这发生在很短的时间里,但若函数只是很简单的几行操作,却要这样来来回回,尤其放在一个循环当中,更是会大大增加函数调用的开销,因此,对于只是实现简单操作的函数,声明其为内联函数,在函数声明前加上关键字inline,即告诉编译器,程序里这个函数出现时,在它所在的位置展开,从而减少函数调用的开销。

inline void printSeparateLine();
inline void printSeparateLine(){
    std::cout<<"--------------------"<<std::endl;
}

但这种方法对稍复杂的函数就不再适用了,在其中不应包含像switch、while这样复杂的结构控制语句,也不该出现递归,否则会被当成普通函数来处理,所以一般情况下并不推荐使用内联函数,除非是一段使用频率很高且很短的代码,才会考虑声明为内联函数。

接上一次实现猜数字的小程序,在本次课中,增加了为其打印分隔线的两个同名函数printSeparateLine(函数的重载)以及实现了一个返回值为字符串类型的函数uppercase_A来演示如何获得来自输入流cin中的一行字符串,并将其中出现的小写’a’变为大写’A’,这里使用到了标准库里的函数getline,它属于std名字空间,第一个变量是一个输入流,第二个变量是用来保存输入流里一行内容的string类型数据(它可能还有另一种3个参数的函数结构,这里用不到)。

以下是这段代码(一些编译环境,可能还需要在前面添加#include <string>

#include <iostream>
inline void printSeparateLine();
void printSeparateLine(int l, char c='-');
using std::string;
string uppercase_A(string str);
int main(int argc, const char * argv[]) {
    using std::cout;
    using std::endl;
    using std::cin;
    int x;
    string str_old, str_new;
    cout<<"Please input a string:"<<endl;
    std::getline(cin,str_old);
    str_new=uppercase_A(str_old);
    cout<<"str_new:"<<str_new<<endl;
    cout<<"str_old:"<<str_old<<endl;
    srand((int)time(0));
    int randomInt = rand()%100+1;
    cout<<"A random integer (1 to 100) has been created."<<endl;
    printSeparateLine(20,'*');
    do{
        cout<<"Please guess the number:"<<endl;
        if(cin>>x&&cin.get()=='\n'){
            if(x==randomInt){
                cout<<"That's right! The number is "<<x<<endl;
                break;
            }else{
                if(x<randomInt){
                    cout<<"The random number is higher."<<endl;
                }else{
                    cout<<"The random number is lower."<<endl;
                }
            }
        }else{
            cin.clear();
            cin.ignore(INT_MAX,'\n');
            cout<<"Please input an integer!"<<endl;
        }
        printSeparateLine();
    }while(true);
    return0;
}

inline void printSeparateLine(){
    std::cout<<"--------------------"<<std::endl;
}

void printSeparateLine(int l, char c){
    for(inti=0;i<l;i++){
        if(i==l-1){
            std::cout<<c<<std::endl;
        }else{
            std::cout<<c;
        }
    }
}

string uppercase_A(string str){
    for(int i=0;i<str.length();i++){
        if(str[i]=='a'){
            str[i]='A';
        }
    }
    return
    str;
}