函数基础、函数重载和函数模板

使用函数的三部曲:函数原型,函数定义,函数调用。为了大家有个直观的认识,举个例子。

#include<stdio.h>
double func(int); //函数原型,可以省略具体参数符号

int main()
{
   int x= func(1); //函数调用
   return x;
  }
double func(int x)  //函数定义
{
return x*x;
}

重点关注一下函数原型。为什么需要函数原型?
感性认识一下,函数原型的意义大概就是声明func是一个函数,当编译器看到这个func时解释为一个函数,那么,只要把func定义放在调用它之前不就不用原型了?
对,这是对的。但是一个良好风格的程序都是main函数放在前面。退一万步说,就算定义放在main函数后面,编译器也可以自己去后面查找函数定义啊,确实可以。但是这个时候就需要停下编译过程去寻找,并且很多时候函数不在这个文件中,在另一个文件。这就很浪费时间,编译器不会这么做。

理解了这一点,我们进一步。函数原型的意义就是确保函数调用时参数的类型和数目准确,以及正确处理函数返回值。具体理解,
如果func没有函数原型,那么double x=func()的调用,编译器是不会报错的,为啥?前面说了,它不会去搜索的,因此不知道传入的参数是什么,不会报错。如果int x=func(1.2),类型错误,也不会报错,最后取64位的前16位作为实际计算参数。
处理返回值:因为函数返回值计算后存储在一个内存地址中,调用结束会找到这的地址并把这个值赋给x,那么取多少字节就是函数原型告诉它的,int就是取四个字节的内容。

函数参数
函数定义的参数是形参,函数调用的参数是实参。同时,形参名也是可以省略的。这里先介绍两种特殊的参数
int func()和int func(void)区别:前者代表你可以传任意参数,函数不会报错,但是并不会接收,函数里不会用到,所以一般人们也不会传入参数,后者代表不能传任何参数,强调作用。
int main(int argc,char *argv[]) : 第一个代表输入参数的个数,第二个参数是一个指针数组,argv[0]指向运行路径,argv[1]指向第一个数,以此类推

函数参数传递三种类型,值传递,指针传递,引用传递。
值传递传的是实参的副本,在函数调用结束后被销毁,而实参不会改变;后面二者传递的是地址,会改变原有的值。并且当参数是很大的结构体或者别的类型时,最好用值传递或者引用传递,不然拷贝空间和时间代价很大。比如数组作为参数时,定义func(int arr[],int n),传入数组名和长度即可,调用时直接用数组名。
引用变量在声明的同时必须初始化,类似于const指针,指向的地方不能改变
函数指针:
声明:只需要把函数名变成 (*pf),把函数名作为参数就是传递了函数指针。
同时也可以用指针调用函数,int x=( *pf)(4) 或者int x=pf(4)

内联函数和宏:内联函数用inline表示,在编译时,直接替换而不是函数调用,因为函数调用需要花销,因此,当一些调用频繁但是函数体较小的函数,可以考虑内联函数。内联函数不能递归。

函数重载,就是对于不同参数数量或者类型,可以用相同的函数名。
比如加法,可以分为浮点数加法和整数加法,两数加法,三数加法等,我们都可以用add表示,比较方便。

函数模板。一种泛型编程,比重载更进一步。比如编写两个整数加法和浮点数加法时,函数体内的代码基本一样的,能不能只写一次呢,这就用到模板
template <typename 标识符>
函数定义
template
T abs(T x)
{
return x<0 ? -x:x;
}

int main()
{
int n = 5;
double d = -2.3;
cout << abs(n) << endl;
cout << abs(d) << endl;
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值