C++基础篇:04 重载、内联、引用

1 函数重载

1.1 什么是函数重载

        在同一作用域下,函数名相同,只要参数列表不同(参数个数不同、类型不同)的函数就构成重载关系

1.2 函数重载与返回值类型、参数名无关

        参数类型不同:普通类型不同、指针类型不同、带不带const属性不同

1.3 C++如何实现函数重载

        g++ -S xxx.cpp生成xxx.s汇编代码可知,编译器会把函数的参数类型个数缩写追加到函数名末尾,也即是编译时函数名会根据参数名换名,所以换名后名字不同可以同时存在

        因为在C++编译器中,编译函数时,会把函数编译成换名后的格式,并且调用函数也会找换名的函数,这样就无法继续调用之前已经同gcc编译器编译好的代码(不换名)

        通过使用extern "C" 告诉C++编译器声明里面的函数按照C语言编译的方式编译函数(不换名),这样就可以让声明与定义匹配,可以继续正确调用标准C库、操作系统函数

1.4 重载与隐藏

        只有在同一作用域下同名不同参的函数构成重载关系

        在不同作用域(父子类)下同名函数遵循名字隐藏原则

1.5 参数类型转换

        当调用函数时,编译器会优先调用类型匹配最精确的那个,如果没有最匹配的,会对参数进行部分类型提升,而不是直接报错

1.6 默认形参

1.6.1什么是默认形参

        在C++中可以给函数的参数设置默认值,当函数被调用时,如果调用者提供了实参则使用实参,如果没提供则使用默认形参

        返回值 函数名(类型 形参名 = 默认值)

1.6.2 默认形参的靠右原则

        如果函数有多个参数,设置默认形参必须从右到左连续设置,否则有歧义

1.6.3 默认形参只能在声明中设置

        如果函数声明与定义时分开实现的,只能在声明时设置默认形参,否则语法错误

1.6.4 默认形参可能会影响函数重载的效果

        如果对函数进行重载,又设置了默认形参,调用时可能会冲突

        因此重载过的函数设置默认形参要谨慎,避免二义性

        void func(int num,int n=88);

        void func(int nun); //有歧义

2 内联函数

2.1普通函数

        会被翻译成二进制指令后存储在代码段中一份,调用语句会生成一条跳转指令,当进程运行到调用语句时,会跳转到函数所在的代码段位置执行,执行结束后再返回原位置

2.2声明是内联函数

        内联函数也会被翻译成二进制指令后调用语句不再生成跳转指令,而是直接把函数的二进制指令替换调用语句,这样函数调用就没有发生跳转也没有返回,而是直接执行被调用函数,这种函数就称为内联函数

2.3实现内联函数

2.3.1 显示内联

            在函数的返回值前面添加inline,该函数就会以内联机制调用    

2.3.2 隐式内联    

            在结构、联合、类中声明以及定义的成员函数会自动被当做内联函数调用

            如果只是在联合、结构、类中声明,但是在外部定义,则不会当做内联函数调用

        注意:函数是否能够被内联执行取决于编译器以及它的优化等级(-On)决定,加inline只可能影响编译器的决定而已

        注意:gcc编译器c99后也支持内联机制

2.4 内联适用的条件

2.4.1内联优点

        节约了函数传参、跳转、返回的时间,提高代码运行效率

2.4.2 内联缺点

        当内联函数在多个位置调用时,那么它的二进制指令就会拷贝多份,产生代码冗余,增大了可执行文件的大小

2.4.3 使用条件

            适合:内容简单且频繁调用的函数,例如for(int i=0;i<10000;i++)}

            不适合内容很多且极少调用的函数

            具有递归特性的函数无法内联,编译器会自动处理为普通函数,会忽略inline关键字

2.4.4 内联函数(inline)与宏函数(define)的相同点与不同点

        相同点:空间换时间策略,提高程序运行效率

        不同点:

            内联函数:返回值、类型检查、安全,入栈、出栈和调用

            宏函数:运行结果、通用、危险

3 引用

3.1 什么是引用

        一种取别名的机制

        格式

            int num = 10;

            int& a = num;

        为什么使用指针:

            ① 函数之间需要共享变量(输出型参数),引用可替代

            ② 提高函数之间的传参效率,引用可替代,甚至效率更高,因为引用不占用字节,没有拷贝

           ③ 与堆内存配合使用,必须使用指针

            ④ 配合字符串,但是string可替代

3.2 使用引用需要注意的问题

        引用必须初始化,所以不存在空的引用

        可以引用右值,但是必须使用const修饰

        引用不可以中途更换引用的目标

        返回值为引用类型时,不要返回局部变量的引用

3.3 什么情况可以使用引用

        跨函数共享变量,使用引用比指针更安全(没有空引用,极少出现野引用),比指针更方便(无需取地址、解引用)

        提高传参效率,引用比指针更高。因为指针还需要传递4/8字节,但是引用一个字节都不需要传递。但是引用也一样存在被修改的风险,因此为了保护引用目标的内容不被修改,也要加const保护

3.4指针与引用的相同点与不同点

        相同点:都可以跨函数共享变量,都可以提高函数传参效率,都需要const保护内容

        不同点:    

            引用是一种取别名的机制,指针是一种数据类型,可以定义指针变量

            引用不需要额外的存储空间,指针变量需要4/8字节的内存来存储地址编号

            引用必须初始化,指针可以不初始化

            引用无空引用,指针可以有空指针

            引用不可以与堆内存配合,指针可以

            可以定义指针数组,但是不能定义引用数组

            注意:可以存在数组的引用 int (&a)[10]=arr;

            可以存在函数引用 void (&f)(void)=func;

4 强制类型转换

        C++中依然可以使用C语言中的那套强制类型转换

为什么C++要重新设计一套强制类型转换的方式?因为C语言中的强制类型转换太危险

    为什么C++强制类型转换设计得这么复杂、使用很麻烦?C++之父认为只因为程序设计不合理的情况下才需要强制类型转换,之所以设计复杂,就是不想让程序员轻松使用,从而反思自己的程序和重新设计自己的程序

4.1 静态类型转换

        static_cast<目标类型>(待转换的数据)

        目标类型与原类型之间必须有一个方向可以自动类型转换,否则报错

4.2 动态类型转换

        dynamic_cast<目标类型>(待转换的数据)

        目标类型与原类型之间必须存在继承关系且只能是指针或引用,否则报错

4.3 去常类型转换

        const_cast<目标类型>(待转换的数据)

        目标类型与原类型之间必须是指针或引用,且除了const属性不同之外,其他都需要相同才可以转换,否则报错

4.4 重解释类型转换

        reinterpret_cast<目标类型>(待转换的数据)

        只能把整数转换成指针或者指针转换成整数,否则报错

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

就酱77叭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值