1.编写函数
- 返回类型
- 函数名
- 参数列表
必须先声明,定义可以延后
- 返回值
必须在每个可能的退出点上将值返回,函数体的最后一句不是return,则这一句就是函数的隐式退出点
2.调用函数
- 传值
传值时,传入的值和原来的值得唯一的联系,就是值相同,相当于复制了一份,在我们调用函数的时候,会在内存中建立一个特殊区域,程序堆栈,为每个函数的参数提供存储空间,一旦函数完成,内存就会释放。这些对象为局部对象。
- 传址
传址的方式传入函数的是对象的地址,而不是复制的一份,采用引用的方式传入。
void display(const vector<int> &vec){
for(int i=0;i<vec.size();i++){
cout << vec[i] << " ";
cout << endl;
}
}
- 作用域和范围
函数内定义的对象,只存在于函数执行的期间,如果把这些局部对象的地址返回,会出错。
int* display(const vector<int> &vec){
int a;
a=3;
return &a;
}
3.默认参数值
void display(const vector<int> &vec,ostream &os=cout){
for(int i=0;i<vec.size();i++){
os << vec[i] << endl;
}
}
定义一个ostream的对象,将其的初值赋值为cout,这样默认的是打印在屏幕上,也可以选择输出到文件中。
4.局部静态对象
const vector<int> *seq(int size){
static vector<int> elems;
return &elems;
}
此时函数可以返回静态局部变量的地址,因为在函数执行结束的时候,elem并不会从内存中消失,依然存在,其存在的范围是当前的文件中。
5.inline函数
inline函数的作用,就是声明当前的函数,要求编译器在每个函数的调用点上,将函数展开。
6.重载函数
不能根据返回值的类型来重载函数,而是参数列表中,参数类型以及参数数量的不同
7.模板函数
template <typename elemtype>
void display_message(const string &msg,const vector<elemtype> &vec){
cout << msg;
for(int i=0;i<vec.size();i++){
elemtype t=vec[i];
cout << t << ' ';
}
}
其实就是定义一个类型,函数不指定类型的输入,elemtype是一个暂时存放类型的占位符。
8.函数指针
首先要注意
int *f(int i, int j);
int (*p)(int i, int j);
第一个是返回指针的函数,第二个是指向函数的函数指针,
函数名和数组类似,也是代表函数所存放的地址,函数名就代表了函数的地址。
- 函数指针的定义
将函数名换成指针,同时制定参数列表。
double add(double x, double y)
{
return x + y;
}
//函数指针
double (*pf)(double,double)=add; //这里(*pf)的括号不能省,不然就不是函数指针了。
- 函数指针的数组
double add(double x, double y)
{
return x + y;
}
double add2(double x, double y)
{
return x - y;
}
double (*pf[2])(double,double) = { add, add2 };
pf是有2个函数指针的数组
- 应用
对于第一种,
#include<iostream>
using namespace std;
double add(double x, double y)
{
return x + y;
}
double calculate(double x1, double y1, double(*f)(double, double)) //函数调用里面传递 函数指针数组 的方法
{
cout << "add:" << (*f)(x1, y1) << endl;
return 1;
}
int main(){
double (*pf)(double,double)=add; //这里(*pf)的括号不能省,不然就不是函数指针了。
int x = 2,y = 1;
calculate(x, y, pf);
//直接calculate(x, y, add);也是可以的
}
第二种:
#include "iostream"
using namespace std;
double add(double, double);
double add2(double x, double y);
double calculate(double x1, double y1, double(*f[])(double, double)) //函数调用里面传递 函数指针数组 的方法
{
cout << "add:" << (*f[0])(x1, y1) << endl;
cout << "add2:" << (*f[1])(x1, y1) << endl;
return 1;
}
int main()
{
int x, y;
double (*pf[2])(double,double) = { add, add2 }; //
x = 2; y = 1;
calculate(x, y, pf); //注意此处的pf,他是函数的名字,就是指针,而这个指针指向的还是指针,即add这个函数名(函数名也是指针),所以在calculate函数的定义中,要用(*f[])或者(**f)
system("pause()");
return 0;
}
double add(double x, double y)
{
return x + y;
}
double add2(double x, double y)
{
return x - y;
}
然后建立函数数组并赋值 double (*pf[2])(double,double) = { add, add2 };
接着传递给上面定义的calculate函数。调用方式为:calculate(x, y, pf);
calculate函数的接收方式应为:double calculate(double x1, double y1, double(**f)(double, double)) //传递的pf是一个数组的数组名且本身也是一个指针,即为二重指针 或者double calculate(double x1, double y1, double(*f[])(double, double))
同时,函数指针不支持自加和自减
函数指针指向的是函数入口地址,每个函数占用的空间是不同的,所以指针增减时就无法确定指针的移动范围,自然没办法指向相邻函数了。
void test(void){
static int temp = 1;
}
int table[5]= {0};
void main(){
printf("数组地址1=%p\n", &table);
printf("数组地址2=%p\n", table);
printf("数组地址3=%p\n",&table+1);
printf("数组地址4=%p\n", table+1);
printf("函数地址1=%p\n", &test); //&test和test其实是一样的,都是函数的地址
printf("函数地址2=%p\n", test);
printf("函数地址3=%p\n", &test+1); // 这个报错
printf("函数地址4=%p\n", test+1); //这个也报错
}
9.头文件
将函数的声明放在头文件中,方便多个程序调用