三、函数的升级

一、内联函数

宏在c语言里有副作用,c++中用const int = 3;的方法解决
c语言里的宏定义可以定义一个代码片段,看起来像函数却不是函数,c++也有类似的解决方案

内联函数:c++中推荐用内联函数代替宏代码片段,c++中用inline关键字声明内联函数
inline int fun(int a, int b)
{
return a

二、内敛函数工作原理:

(1).c++编译器可以将一个函数进行内敛编译成为内敛函数
(2).内联函数在最终生成的代码中是没有定义的,c++编译器直接将函数体插入到函数定义的地方
(3).内联函数没有普通函数调用时的额外开销(压栈、跳转、返回)
注:c++编译器不一定允许函数的内联请求(类似于c语言中的register)

#include<stdio.h>
inline int fun(int a, int b)
{
    return a < b ? a : b;
}
int main()
{
    int c;
    c = fun(2,3);//相当于c = 2 < 3? 2:3;
    printf("%d",c);
    getchar();
    return 0;
}

三、内联函数与宏定义的区别:

(1).内联函数是一种特殊的函数,具有普通的函数的特征(参数检查、返回类型等)
(2).内联函数是对编译器的一种请求(类似于C语言的register),编译器可能拒绝这种请求
(3).内联函数由编译器处理,直接将编译后的函数体插入调用的地方,而宏代码片段由编译器处理,进行简单的文本替换,没有任何编译过程,所以说内联函数比宏代码片段安全。

四、c++中内联函数编译的限制:

(1).不能存在任何形式的循环语句
(2).不能存在过多的条件判断语句
(3).函数体不能过于庞大
(4).不能对函数进行取值操作
(5).函数内联声明必须在调用语句之前
(6).编译器对于内联函数的限制并不是绝对的。

五、c++中内联函数的实现机制:

(1).检查函数是否够小符合要求
(2).将内联函数放入符号表中(符号表与最终生成的程序无关,只是编译器自己用的东西),直接到符号表里将函数体取出来放到调用的地方

六、函数默认参数

(1).c++中可以在函数声明声明声明时为参数提供一个默认值(函数在main函数之前时是声明和定义在一起)
当函数调用时没有指定这个参数的值,编译器会自动用默认值代替

#include<stdio.h>
int fun(int x = 6);//声明时指定函数的默认参数
int main()
{
    printf("%d\n",fun());
    getchar();
    return 0;
}
int fun(int x)//定义时不用再声明
{
    return x;
}

结果会打印出6;
(2).有多个参数时,在某个参数为起点,后面的参数必须提供默认值如int fun(int a, int b=0, int c=0);即
在b参数开始提供默认值,b后面的参数都要提供默认值,否则报错(调用时也一样,从第几个参数使用默认值,其后的所有参数都需要默认值)

#include<stdio.h>
int fun(int a,int b = 3,int x = 6);//从b开始,所以后面也必须提供默认参数
int main()
{
    printf("%d\n",fun(2));//调用时要注意给没有默认参数的传递实参
    getchar();
    return 0;
}
int fun(int a,int b,int x)//定义时不用再声明
{
    return x;
}

七、函数占位参数

占位参数只有参数类型声明,而没有函数声明
一般情况下函数体内部无法使用占位参数(因为没有名字)
int fun(int a, int b, int)//调用时必须提供三个参数,
{
return a+b;
}
要占位参数的意义:可以将占位参数与默认参数结合起来使用
int fun(int a, int b, int = 0)
{
return a+b;
}
意义:
为以后的程序的拓展留下线索(功能目前够了,以后需要其他功能可拓展)
兼容C语言中可能出现的不规范写法(c函数没有定义参数,可以传入任意参数)

八、重载:同样的标识符在不同的上下文中有不同的意义

1.函数重载满足下列条件之一:
(1).参数个数不同
(2).参数类型不同
(3).参数顺序不同

#include<stdio.h>
int fun(char c)//只有一个char参数
{
    printf("I am funone\n");
    return 0;
}
int fun(int a)//只有一个int参数
{
    printf("I am funtwo\n");
    return 0;
}
int fun(int a,char c)
{
    printf("I am funthree\n");
    return 0;
}
int fun(char c,int a)
{
    printf("I am funfour\n");
    return 0;
}
int main()
{

    fun('c');//打印I am funone
    fun(3);//打印I am funtwo
    fun(3,'a');//打印I am funthree
    fun('a',3);//打印I am funfour
    getchar();
    return 0;
}

2.当函数默认参数遇到函数重载

#include<stdio.h>
int fun(int a,int c,int d = 0)
{
    printf("I am funthree\n");
    return 0;
}
int fun(int a,int c)
{
    printf("I am funfour\n");
    return 0;
}
int main()
{
    fun(1,2);//以上函数都可以调用,这样编译器就会告诉说调用函数不明确,产生了二义性
    getchar();
    return 0;
}

(3).编译器调用重载函数的准则:
将所有同名的函数作为候选者
尝试寻找可行的候选函数
精确匹配实参(找到这个int fun(int x,int y))
通过默认参数能够匹配实参(找到int fun(int x,int y, int c =0))
通过默认类型转换匹配实参
如果上面的main函数调用为fun(‘a’, 2),就会找到int fun(int x,int y),假设什么已经删掉了默认参数
匹配失败
最终寻找到的可行候选函数不唯一,则出现二义性,编译失败
无法匹配所有候选者,函数未定义,编译失败
注:重载函数与返回值类型无关,只与参数类型和参数列表无关

函数重载与函数指针:
当使用重载函数名对函数指针进行赋值时
根据重载规则挑选与函数指针参数参数参数列表一致的候选者
严格匹配候选者的函数类型和函数指针类型(包括返回值和参数)

#include<stdio.h>
typedef int(*PFUN)(int a);//类型是int(int)
int fun(int a)
{

    return a;
}
int main()
{
    PFUN p;
    int c;
    p = fun;
    c = p(2);
    printf("%d\n",c);
    getchar();
    return 0;
}

但如果typedef void(*PFUNC)(int a);//类型为void(int a)则报错,因为返回值和参数都要匹配

九、c++与c的相互调用

c++编译器能够兼容C语言的编译方式,但会优先使用c++编译方式进行编译
利用extern关键字强制让c++编译器对代码进行c方式编译
c++调用c代码(用extern)
extern “c”
{
#include”add.h”//里面是c函数的声明
}

c调用c++代码:编译c++时先使用c的方式编译再把.o文件给c

统一解决方案:__cplusplus是c++编译器内置的标准宏定义
__cplusplus:的意义:
让c代码即可通过c编译器编译,也可以在c++编译器中以c的方式编译

ifdef __cplusplus

extern “c”{

endif

//函数声明或函数定义

ifdef __cplusplus

}

endif

注:c++编译器不能以c的方式编译多个重载函数

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值