函数其实就是一段封装起来的具有特定功能的代码,你可以把它当成工具,工具就是为了给我们带来便利。一些经常用到的函数,比如sort()排序函数,比如你修车需要拧螺丝,你想起来对应型号的扳手工具箱里有就拿来使(这就是用头文件里的函数)。但是你要是没想起来有,咋办,用现有的条件临时造一个,然后搁一边,方便后面还要用(也就是自己写的函数)。那工具还分不同类型呢,函数也一样,按照返回的不同,可分为无返回值的( 也就是函数开头是 void 的无类型的)和有返回值的(开头是int 的就能返int型的数,是double就能返回double型的等等)。有了工具你还得知道该怎末使用,就好比电钻你得插上电才能拿它钻墙,要想使用含函数首先要满足特定的条件,才能在合适的位置发挥它特定的作用,就比如传递一个数组的首地址和长度给sort(),像这样 sort(a,10); 然后数组 a[n] 中 a[0] 到 a[9] 这10个数就会按从小到大的顺序排列。
1.函数的定义
写一个函数一般有五个步骤:
1返回值类型,void, int ,double ,char,int* ...
2.函数名
3.参数列表 //从这我们就能找到使用这个函数需要传入什么数据,没有那就不用传。
4.函数体语句
5.return 表达式
#include<bits/stdc++.h>
using namespace std;
//例:写一个实现两个数相加求和的函数
//函数的定义
int add(int num1,int num2)
{
int sum;
sum=num1+num2;
return sum;
}
int main(void)
{
int sum;
int a=10,b=20;
sum=add(a,b); //函数的调用
cout<<sum<<endl;
cout<<add(a,b)<<endl;
return 0;
}
2.函数的调用
语法:函数名(参数);
void类型函数你把他当成一段代码来用就行。
其他返回值如果是int型的比如上面写的函数,用的时候就相当于是一个整数,你可以把它赋值给一个同类型变量,比如 int c=add(10,20); 相当于 int c=10+20; 。或者直接输出 cout<<add(10,20); 输出的结果就是 30。10、20也可以换成其他你定义的变量比如 add(a,b); 但a,b必须是int型的,因为add这个函数的参数列表里的两个形参是int 型。
3.值传递
就是函数调用时将实参的值传递给形参。如上面代码num1,num2,在sum函数里面定义的是形参(被函数调用的函数里面的参数),sum,a,b 在main()函数里面定义的 是实参(调用函数的函数里面的参数)。
值传递时,形参不影响实参,比如函数里面也定义了一个变量 sum,但如果不是有这段代码sum=add(a,b); 将返回值sum赋值给了main()函数里的sum, 那么函数里的sum怎么变,都不会改变main()函数中sum的值。
4.函数的声明
函数声明的作用就是告诉编译器函数的名称以及如何调用函数。然后可以在声明下面单独定义函数。通常我们定义一个函数需要把这个函数写在main()函数上面,不然就不能在main()函数中调用这个函数,但是如果你在函数上面写一个声明,就可以在amin()函数下面来定义这个函数。
#include<bits/stdc++.h>
using namespace std;
//下面是函数的声明
int test(int a,int b);
int main()
{
int a=10,b=10;
cout<<test(a,b)<<endl;
return 0
}
//函数的定义
int test(int a,int b)
{
return a+b;
}
5. 函数的分文件编写
在写一些很长的代码时,你可能要写很多的函数,如果都放在一个文件中找起来会不方便,一个项目你得写好几天,可能有时候你写过的函数写着写着就忘记了,用函数份文件编写让代码结构更清晰。
分文件编写步骤:
1,创建一个后缀为.h的头文件,->>在这里面写函数的声明
2,创建一个后缀为.cpp的源文件,->>在这里面写函数的定义
然后就可以加个头文件,无需再定义函数,直接调用函数。注意有些编译器可能不支持这方式,VS可以其他的不知道。
6.函数的默认参数
函数的形参是可以有默认值的,比如下面这个函数
int add(int a,int b,int c)
{
return a+b+c;
}
你如果想调用它必须给他传递三个值才行,不然就会报错
int sum=add(10,20,30);//最终sum的值为60
但如果你给形参一个默认值,比如让c=10; 这就叫默认参数
int add(int a,int b,int c=10)
{
return a+b+c;
}
然后你就可以输入两个值就OK,其中c的值默认为10
int sum=add(10,20);//最终sum的值为40
也可以传递三个值,这样你传递的第三个数就会覆盖掉c的默认值。
int sum=add(10,20,40);//最终sum的值为70
注意:1如果你给一个形参默认值,那么他后面的每一个形参都要给一个默认值,不然会报错。
2函数声明和函数定义的参数表里只能有一个里面有默认参数。
7. 函数的重载
我理解的比较浅薄,就是说函数可以用同一个名字实现不同的功能,为了提高函数复用性。在类里用的多吧,调用函数除了要使用函数名外,还要满足调用的条件,比如不传递值,传递一个值,传递两个值,传递一个地址等等,所以说函数名可以相同,但是函数的参数表要不同(类型不同或者个数不同或者顺序不同)。这样我们在调用函数是根据传入的参数不同来调用不同的函数,否则编译器会不知道该调用哪个。
注意:函数的重载必须作用在同一个作用域下,比如说我们通常定义函数都是在全局作用域中
函数的返回值不同不能作为重载条件
int test(int a)
{
return a*a;
}
int test(int a,int b) //个数不同
{
return a+b;
}
void test(int a) //返回值不同,是不允许的,编译会报错
{
cout<<a<<endl;
}
void test(char a) //类型不同
{
cout<<a<<endl;
}
void test(char a,int b) ///
{
cout<<a<<endl;
}
void test(int a,char b) ///顺序不同
{
cout<<a<<endl;
}
还有就是引用做函数参数的重载,但要注意调用的是哪个,
void test(int &b)
{
cout<<"test1"<<endl;
}
void test(const int b) //这也是类型不同
{
cout<<"test2"<<endl;
}
int main()
{
int a=10;
test(a); //这个会输出test1,int &a = a是合法的,const int b = a不合法
test(10); //这个会输出test2,10是个常数,const int b = 10合法,int &a = 10不合法的
return 0;
}
还有就是函数重载碰到默认参数的情况,可能会导致编译器不知道该调用哪个函数,因为个数不同的函数,比如下面这俩,如果你 t=test(10);那么两个都能被调用,这样是不行滴。
int test(int a)
{
return a*a;
}
int test(int a,int b=10) //个数不同
{
return a+b