c++函数

c++函数,第1张

文章目录
  • 函数
    • 函数简介
      • 函数的定义
      • 函数调用
      • 函数的作用域
      • 参数
      • 返回值
      • 静态局部对象

函数

函数(Function)是c++的一个核心概念,在一些语言中类似的概念也叫做方法(Method)。


计算机的核心组成是数据和指令,函数可以把这两者结合起来抽象成一个宏观的 *** 作。


main()函数或者vector的push_back()都是函数。


对于push_back来说,它所做的 *** 作就是把一个数据元素推入当前的vector。


函数的实现中可能有许多语句或指令,也会额外声明很多局部的变量,但是对于这个函数的使用者来说,他并不需要关心函数的实现细节,只要知道函数可以做什么就可以了。


函数简介

函数作为一个黑匣子,需要定义输入接口的个数和类型,也就是参数,对于收音机来说就是电源插头、天线以及按钮。


函数也要定义输出内容的类型,对于收音机来说就是声音,一般的函数只输出一个值。


定义完函数之后,在使用的时候我们要给定实际的输出,对于收音机来说就是把插头接到插座、将信号传到天线和按下播放按钮,完成这些 *** 作之后收音机就会按照一些看不见的原理输出声音,这也就是函数调用(call)的过程。


函数的定义

函数作为一种开发人员自定义的宏观 *** 作,其组成元素也与 *** 作符类似。


*** 作符由符号本身、 *** 作数和返回结果组成,而函数也于此类似:符号对应着自定义的函数名, *** 作数对应函数参数,而返回值结果对应着函数返回值。


此外,函数 *** 作还需要一个函数体来具体实现函数的 *** 作。


简单函数的定义

#include
using namespace std;

//函数定义

int max(int a, int b)
{
	return ((a > b) ? a : b);
}

可以看到,在函数定义中,函数名是max,函数是a和b,他们的类型都是 int 。


在这里,函数定义的参数叫形式参数或形参(Parameter)。


此外,这个函数的返回值类型(Rsturn Type)也是 int 。


在括号中的参数列表之后紧跟着的就是被花括号包裹的函数体了。


这个函数体唯一的一个语句是返回语句,,它将a和b中的最大值返回给了使用函数的外层语句。



在这里,函数体外的函数名、形参以及返回值的整体又称为函数签名(Function Signature)或着接口(Iinterface)。



函数调用

在定义了函数之后,需要在实际应用中调用这个函数。


调用函数时我们使用函数调用 *** 作符“()”(Function Call Operator),并将实际的参数值,也叫实参(Argument),填入括号中。


形参和实参的区别用数学中的概念来解释就非常容易懂:对于y=kx+b这个函数来说,k和b这两个常量是在函数内部定义的局部变量,x就是函数定义中的形参,而y是函数的返回值;而当把数值1带入公式的时候,函数调用的实际返回值就是k+b,在这里函数的实参就是1.

函数调用

#include 
using namespace std;

//函数调用

int max(int a, int b){
	return ((a > b) ? a : b);
}

	int main()
	{
		int a = 3;
		int b = 4;
		int c = max(a, b);
		cout << "a与b最大的值是: " << c << endl;
		return 0;
	}

运行结果
可以看到,在调用max()函数的时候我们传入了实参a 和b ,而函数再返回的时候将返回值赋值给了c.


函数的作用域

函数体的定义是用花括号框起来的,这样我们自然会想到作用域的定义。


函数作为程序中相对独立的一个有机体,也有自己的作用域。


反过来说,如果函数没有作用域,其中定义的局部变量还会干扰外层的变量,这样就违背了函数隐藏实现的初衷。


函数局部作用域

#include
using namespace std;

//函数局部作用域

void printSomething()
{
	int something = 3;{
	int something = 5;
	cout << "在printSomething开头,something的值为: " << something << endl;
}
	cout << "在printSomething最后,something的值为: " << something << endl;
	
	}
int main()
{
	//printSomething中这个变量定义不可见
	int something = 4;
	printSomething();
	cout << "在main函数中,something的值为:"  << something << endl;
	return 0;
}

运行结果

可以看到,函数中也可以添加局部作用域块,而其中定义的局部变量会屏蔽函数一开始定义的同名变量。


此外,在main()函数中调用printSomething前定义 的局部变量在函数定义中不可见,这点与可控制语句不一样。


全局变量对函数的影响

#include
using namespace std;

//全局变量对函数的影响

int something = 5;

void printSomething()
{
	cout << "在printSomething最后,something的值为:" << something << endl;
}
int main()
{
	printSomething();
	cout << "在main函数中,something的值为:" << something << endl;
       return 0;
}

运行结果

可见,无论是在自定义函数printSomething中还是在main()函数中,全局变量都是可见的。


函数作用域的综合示例

#include
using namespace std;

//函数作用域的综合示例

int something = 5;

void printSomething()
{
	cout << "在printSomething开头,something的值为:" << something << endl;
	int something = 3 ;
	cout << "在printSomrthing最后,something的值为:" << something << endl;
}
 
int main()
{
	cout << "在main函数开头,something的值为: " << something << endl;
       int something = 4;
	printSomething();
 	cout << "在main函数最后,something的值为:" << something << endl;
	return 0;
}

运行结果

可以看到,printSomething()函数中声明的局部变量something屏蔽了同步的全局变量something,因此声明something之后打印的结果就从5变成了3;而main()函数中的局部变量也屏蔽了全局变量,因此打印的结果也从一开始的5变成了4.这里需要注意的是,虽然main()函数调用了printsomething(),但是两个函数还是并列的关系,函数的定义都处于全局作用域之下。



此外,printsomething的返回值类型是void。



参数

函数的参数分为形参和实参两种,实参的个数必须与形参相同,而实参的类型也必须与形参相同,或者至少能进行隐式转换。


一个函数也可以没有任何参数,这种情况下括号中就是空的。


实参与形参不匹配

#include
using namespace std;

//实参与形参不匹配

void doSomething(int a)
{
}
void doNothing ()
{
}
int main()
{
        doSomething ();
        doNothing (3);
        return 0;
}

doSomething()函数需要一个参数而实际一个都没有传入,而doNothing()函数不需要任何参数却实际传入了一个参数,这两种情况都是编译器无法接受的。



如果需要更清晰的表达函数不需要参数的意思,我们可以在括号中只写一个void作为参数列表,就像doNothing(void)这样。



返回值

对于函数,我们都要指定它的返回值类型。


虽然一个函数可能会返回上一个值,但是也也不一定要用这个值,类似于“doSomething()”这样的语句也是没有问题的,只是有的时候可能确实忘记使用函数返回值了。


如果函数没有返回值,也需要指定它的返回值类型为void,这样一来,在函数体中就不需要添加return语句了。


错误使用返回值为void的函数

#include
using namespace std;

//错误使用返回值为void的函数

void doNothing ()
{
	return 1;
}

int main()
{
	int num = doNothing();
	return 0;
}

示例展示了两种错误使用返回值为void的函数情况。



可以看到,在doNothing()函数定义的函数体中我们添加了return语句,这与void的返回值类型不匹配。


而在main()函数中我们也将doNothing的返回值赋值给了num,这显然也是不行的。


不过返回值为void的函数也可以用“return”这样的语句提前退出函数,而不会返回实际数值。


返回值为void的函数中提前返回

#include
using namespace std;

//返回值为void的函数中的提前返回

void doNothingForOne (int num)
{
	if ( num == 1) 
	{
		return ;
	}
	cout <<"num的值为:" <<num << endl;
}

int main()
{
	doNothingForOne(2);
	doNothingForOne(1);
	doNothingForOne(0);
	return 0;
}

** 运行结果**

可以看到示例中doNothingForOne()函数在参数为1的时候会直接返回,而不执行后面的打印语句。


这里return只提供了跳转功能,并没有返回任何值。



静态局部对象

静态局部对象不会随着函数返回而销毁,而是从程序开始到结束一直存在,它与全局对象的区别就是其只在函数的作用域中可见。


#include
using namespace std;

//静态局部对象

void printAndCnt(int num)
{
	static int cnt = 0;
	cnt++;
	cout <<"打印数字:" << num << endl;
	cout <<"函数被调用了" << cnt << "次" << endl;
}

int main()
{
	for ( int i = 0;i < 10 ;i+=2 )
	{
		printAndCnt(i);
	}
	return 0;
}

运行结果

在函数定义中定义了一个静态局部变量cnt并初始化为0,它与普通局部变量的区别就是有一个static关键字。


在main()函数的循环中我们一共调用了5次,而cnt也从0累加到了5.


如果对你有帮助,点个赞支持一下吧~

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/568757.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-09
下一篇 2022-04-09

发表评论

登录后才能评论

评论列表(0条)

保存