一.函数格式
函数定义:提供了函数的编译代码
函数头
函数体
函数原型:使得编译器知道函数的返回值和参数列表,有两种方法为文件提供原型
源文件中手动输入
头文件包含
可变参数原型需要明示如void function(...)
ANSI C中可变参数的原型可以写成void funtion() 和void参数一样
作用:告诉参数列表,告诉返回值(接口)
也只需要函数接口信息—-故可以省略参数名称
void function(int , double) 合法
:为何不从函数定义中获取这些信息
效率不高:搜索时暂停编译
可能位于其他文件中:编译时可能无权访问,在链接的时候才能凑出完整程序
函数默认值
通过原型告诉,而非定义
若要为某个形参指定默认值,其右边形参也必须指定
传递参数时,实参要从左到右依次键入,不可中间跳跃,有默认值的可省略
编译指令using
二.参数传递
xing
形参列表:/-简单变量/-数组形参/-指针形参/-结构形参
简单变量
按值传递,强制转换
流程:先新建一个自动变量—-拷贝值—-退出函数后销毁
数组
传递的是指针而非数组名
int a[3] = {1, 2, 3} ;
void fun1 (int b[])
{
b[1] == 1 ; //可以像正常数组使用
sizeof(b) == 4 ; //sizeof结果是指针的大小为4 而非sizeof(a) == 12
}
Copy
C++
const int a[] 等价于 const int *a
结构体
按值传递
由于类对象基于结构体,故模板类(vector array)也是按值传递,string类也是
const返回比较
常规
引用
在cout示例中,返回自身可以写出串联表达式
const 引用
减少开销,如果有引用传入,此项最佳,常规按值返回的的量也为不可修改的值
但是不能返回临时变量(会被销毁)
const 常规
为避免写出epr1 + epr2 = var1
epr1+epr2会返回的临时对象,理应不可修改,故加const
函数指针
|-简单函数指针-|-函数指针数组-|
//简单定义初始化
int fun1( int a ) {...} ;
int (*pf1)(int) = fun1 //简单声明加初始化
//区别函数调用和函数地址 函数调用为fun1(...)
//指针调用
pf1(4) ;
//或
(*pf)(4) ;
Copy
C++
简单声明调用:如上
函数指针(指针返回值)—-函数指针数组:如下
//先定义一个指针返回函数
double *fun2 (double a, double b) {...} ;
//则对应函数指针
double *(*pf2) (double, double) = fun2;
//将标识符替换成(*pf2)即可
//函数指针数组
double *(*pf2[3]) (double, double) = fun2;
//[3]先结合说明是数组,其余部分说明类型
//还可新建指向函数指针数组的指针
auto pf3 = & pf2
//或者手写
//同样将标识符替换
double *(*(*pf3)[3]) (double, double) = & pf2 ;
Copy
C++
内联
无跨文件访问,只能单一文件访问(每个文件都必须定义)
所以一般放置于头文件中
在原来原型声明的地方完成定义(类似小函数的写法)
三.函数重载
根据函数的特征标(形参)进行重载
不区分const和非const 不区分引用和原始
返回值可以不同,但特征标也必须不同
重载解析过程
创建候选列表—-同名的函数或模板及其重载
创建可行参数列表—-完全匹配>提升匹配(int→long)>标准匹配(int→char/long→double)
确定是否有可行函数
对于完全匹配也可有某些无关紧要的匹配
无关紧要匹配列表
实参—|—形参
Type <--> Type &
Type --> const Type
Type --> volatile Type
Type[] --> Type *
Copy
C++
若完全匹配,则非模板>模板
若完全匹配均为模板函数,则较为具体的优先(显式具体>隐式实例)
多参数则跟脚麻烦此处不赘述
decltype
//例一
int x ;
decltype( x ) ; //为int
//例二
int a ;
decltype( (a) ) ; //为int&
Copy
C++
语法decltype( expression )
若为无括号标识符则和标识符类型相同
若为函数调用,则和返回值相同
左值,则为其引用—→带括号标识符,则为引用
前面都不满足,则为expression的类型
模板函数是占位声明
由于模板,可能存在无法判断返回值的类型
可用auto占位,后置类型声明
template<typename Type1, typename Type2>
auto fun1 (Type1 var1,Type2 var2) -> decltype(var1+var2)
{
...
}
Copy
C++
四.函数模板
简单模板的定义声明调用
template <typename AnyType>
void Swap( AnyType &a, AnyType &b ) //原型
int main()
{
int i = 1 , j = 2 ;
Swap(i,j) ; //隐式实例化
}
template <typename AnyType>
void Swap( AnyType &a, AnyType &b ) //定义
{
AnyType temp ;
temp = a ;
a = b ;
b = temp ;
return ;
}
Copy
C++
重载模板函数
可以混用未定义类和已知类,仍然通过特征标区别
template <typename AnyType>
void Swap(AnyType &a, AnyType &b, int n){...};
Copy
C++
显示具体化—-显示实例化
//具体化(重写模板)
template <> void Swap (int &a, int &b) ; //原型
//或---<job>可选
template <> void Swap<job> (int &a, int &b) ; //原型
//实例化(区别隐式实例化)
template void Swap<job> (int &a, int &b) ; //原型
Copy
C++