函数
基本概念
main函数
程序的主入口 必有一个
int main (){
return 0; // 0 表示成功 其他值失败
}
不能函数内部再定义函数
函数的定义
定义返回值
没有返回值用void
返回值不能直接是数组,但是可以是指针,结构(结构中嵌套数组就可以)
不能返回内部变量的 指针,地址,引用
定义函数名
符合命名规范即可,最好见名知义
定义函数参数
某些类型存在自动转换 例如int,double 互转
但是最好不要这样 因为函数重载可能导致二义性
参数的三种形式
按值传递
void fn1(int x); 传入的是5 则相当于 声明一个x变量并赋值为5
按地址
按引用 能按引用按引用
更多见下面
定义函数体
函数参数
常见形式
1、数字 字符 bool
因为占用字节小直接按值即可
2、数组
int sumArr(int arr[],int n);
int sumArr(int* arr,int n); 一般写成这样的形式
仅当在函数头中时 int arr[] 才和int* arr含义相同
int* arr 也可以是数字类型指针 数字类型可以直接按值传递 所以这里当做 数组指针
arr是一个数组名,也是一个数组指针,到函数内部时则是指针了,所以必须传数组长度
内部修改数组 会修改数组本身
int sumArr(const int* arr,int n);
内部防止修改 用const
只意味着在这个函数中 arr是常量数组
3、多维数组
void testDefine(int arr1[][4],int (*arr2)[4]);
int list[2][4] = {
{1,2,3,4},
{1}
};
testDefine(list,list); // 多种格式 效果相同
4、字符串
字符串等同于字符数组等同于数组 ,因为字符串有结束字符,所以不必要知道长度
但是存在三种情况 其实都是char*
1 char数组
2 双引号常量值
3 char指针
void fn(char* str1,char str2[],char** str3)
char** str3 接受 下面类型数据
char *str1[] = {
"aaa",
"b"
};
5、结构体struct
可以按值传递,但是效率不高
还是推荐用地址传值或引用传值 C++中最好用此
void testFn(JS1 s1,JS1& s2,JS1* s3)
s1 按值 不推荐
s2 按引用 推荐
s3 按地址
6、class类
类似于结构
7、函数作为参数
typedef int (*fn)(int); 声明函数原型
void testFn(fn f1)
int getValue(int a);
testFn(getValue); // 传递函数
默认参数
int fn1(const int arr[],int n = 1); 原型
只有原型需要定义默认值 函数定义不用
其他 使用同其他语言
可变参数
void testfn(char s1,int n1,...){
va_list ap;
va_start(ap, n1);
for (int j = 1; j <= 3; ++j) {
std::cout << va_arg(ap,int) << std::endl;
}
va_end(ap);
}
testfn('a',1,2,3,4,5,6);
函数的原型
提前告知编译器 提高效率 同时检查函数调用是否正确
函数原型其实就是函数头+分号,只是可以不用参数变量名
函数指针
获取函数地址
函数名本身就是函数地址
声明函数指针
写好原型后 把函数名 变为(*函数名) 则是该函数类型指针
这个指针可以指向 (只要是这个返回值并且是这个参数类型) 的函数
int fn(int a) 指针为 int (*p_fn)(int) = fn
用指针调用函数
*p_fn() === fn() 这种明显指出用指针调用函数
p_fn() == fn() 也可以
函数指针数组
int (*fn[3])(int) = {f1,f2,f3}; 此时不能使用auto
指向函数指针数组的指针
不告诉你怎么写
inline 内联函数
速度快 但是占用内存大,所以有选择的使用 太长太大的函数 不适合做为内联函数
比宏更好用
内联函数不能递归调用
在函数声明或定义前加 inline 通常省略原型 直接完整定义 声明为内联函数
但是编译器不一定满足这种要求,例如 函数过大或自身递归,或编译器没有这个特性
inline int fn1(int num){return num}
函数重载 多态
在类中详细介绍 例如重载构造函数
能够通过上下文使用多个同名的函数
同名函数必须参数特征不同
类型引用和类型本身视为同一个值
情况1 完成类似工作 可以使用重载
完成相同的工作,使用不同的参数列表
情况2 这种情况 最好不用重载
完成不同的工作,使用不同的参数列表