C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析

内联函数分析

1常量与宏回顾

  • C++中的const常量可以替代宏常数定义
    • 如:const int A = 3;  < --- --->  #define A (无类型检查)
    • C++中是否有解决方案替代宏代码片段呢?

2内联函数

  • C++中推荐使用内联函数替代宏代码片段
  • C++中使用inline关键字声明内联函数
  • C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第1张图片
  • 内联函数声明时inline关键字必须和函数定义结合在一起,否则编译器会直接忽略内联请求。
  • C++编译器可以将一个函数进行内联编译
  • 被C++编译器内联编译的函数叫做内联函数
  • C++编译器直接将函数体插入函数调用的地方
  • 内联函数没有普通函数调用时的额外开销(压栈,跳转,返回)
  • C++编译器不一定满足函数的内联请求!

3、编程实验:内联函数初探

        C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第2张图片

        C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第3张图片

4、内联函数

  • 内联函数具有普通函数的特征(参数检查返回类型等)
  • 函数的内联请求可能被编译器拒绝
  • 函数被内联编译后,函数体直接扩展到调用的地方
  • 宏代码片段由预处理器处理,进行简单的文本替换,没有任何编译过程,因此可能出现副作用。

        C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第4张图片

  • 现代C++编译器能够进行编译优化,一些函数即使没有inline声明,也可能被内联编译
  • —些现代C++编译器提供了扩展语法,能够对函数进行强制内联,如:
    • g++ :_attribute__((always_inline))属性
    • MSVC :_forceinline

5、编程实验:内联函数深度示例

C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第5张图片

6、注意事项

  • C++中inline内联编译的限制
    • 不能存在任何形式的循环语句
    • 不能存在过多的条件判断语句
    • 函数体不能过于庞大
    • 不能对函数进行取址操作
    • 函数内联声明必须在调用语句之前

7、小结

  • C++中可以通过inline声明内联函数
  • 编译器直接将内联函数体扩展到函数调用的地方
  • inline只是一种请求,编译器不一定允许这种请求
  • 内联函数省去了函数调用时压栈,跳转返回的开销

函数参数的扩展

1函数参数的默认值

  • C++中可以在函数声明时为参数提供一个默认值
  • 当函数调用时没有提供参数的值,则使用默认值

        C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第6张图片

  • 参数的默认值必须在函数声明中指定
  • 问题︰
    • 函数定义中是否可以出现参数的默认值?不可以出现
    • 当函数声明和定义中的参数默认值不同时会发生什么?报错

        C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第7张图片

  • 函数默认参数的规则
    • 参数的默认值必须从右向左提供
    • 函数调用时使用了默认值,则后续参数必须使用默认值

        C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第8张图片

  • 编程实验:默认参数的错误示例

        C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第9张图片

2、函数占位参数

  • 在C++中可以为函数提供占位参数
    • 占位参数只有参数类型声明,而没有参数名声明
    • —般情况下,在函数体内部无法使用占位参数

        C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第10张图片

  • 函数占位参数的意义
    • 占位参数与默认参数结合起来使用
    • 兼容C语言程序中可能出现的不规范写法

        C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第11张图片

  • 编程实验:占位参数与默认参数值

        C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第12张图片

3、小结

  • C++中支持函数参数的默认值
  • 如果函数调用时没有提供参数值,则使用默认值
  • 参数的默认值必须从右向左提供
  • 函数调用时使用了默认值,则后续参数必须使用默认值
  • C++中支持占位参数(可以配合默认参数值),用于兼容c语言中的不规范写法

函数重载分析(上)

1自然语言中的上下文

C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第13张图片

2重载的概念

  • 重载(Overload)
    • 同一个标识符在不同的上下文有不同的意义
    • 如:
      • “洗”和不同的词汇搭配后有不同的含义
        • 洗衣服,洗脸,洗脑,洗马桶,。。。
      • "play”和不同的单词搭配后有不同的含义
        • play chess, play piano, play basketball, ...

3思考。。

重载在自然语言中是随处可见的。那么程序设计中是否也有重载呢?

4C++中的函数重载

  • 函数重载(Function Overload)
    • 用同一个函数名定义不同的函数
    • 当函数名和不同的参数搭配时函数的含义不同

C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第14张图片

  • 函数重载至少满足下面的一个条件:
    • 参数个数不同
    • 参数类型不同
    • 参数顺序不同

C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第15张图片

  • 上面的两个函数可以构成重载函数吗?可以
  • 当函数默认参数遇上丞数重载会发生什么?

C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第16张图片

  • 编程实验:函数默认参数VS函数重载

C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第17张图片

5编译器调用重载函数的准则

  • 将所有同名函数作为候选者
  • 尝试寻找可行的候选函数
    • 精确匹配实参
    • 通过默认参数能够匹配实参
    • 通过默认类型转换匹配实参
  • 匹配失败
    • 最终寻找到的候选函数不唯一,则出现二义性,编译失败。
    • 无法匹配所有候选者,函数未定义,编译失败。

6重载函数的注意事项

  • 重载函数在本质上是相互独立的不同函数
  • 重载函数的函数类型不同
  • 函数返回值不能作为函数重载的依据
  • 函数重载是由函数名参数列表决定的
  • 编程实验:函数重载的本质

C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第18张图片

7、小结

  • 函数重载是C++中引入的概念
  • 函数重载用于模拟自然语言中的词汇搭配
  • 函数重载使得C++具有更丰富的语义表达能力
  • 函数重载的本质为相互独立的不同函数
  • C++中通过函数名函数参数确定函数调用

函数重载分析(下)

1重载与指针

下面的函数指针将保存哪个函数的地址?第一个

C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第19张图片

2函数重载遇上函数指针

  • 重载函数名赋值给函数指针
    • 根据重载规则挑选与函数指针参数列表一致的候选者
    • 严格匹配候选者的函数类型与函数指针的函数类型(即返回值也必须一致
  • 编程实验:函数重载VS函数指针

C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第20张图片

3注意

  • 函数重载必然发生在同一个作用域中
  • 编译器需要用进参数列表函数类型行函数选择
  • 无法直接通过函数名得到重载函数的入口地址

ps:函数的类型由返回值参数类型参数个数共同决定;函数类型 = 参数列表 + 返回值

C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第21张图片

4C++和C相互调用

  • 实际工程中C++C代码相互调用是不可避免的
  • C++编译器能够兼容C语言的编译方式
  • C++编译器会优先使用C++编译的方式
  • extern关键字能强制让C++编译器进行C方式的编译

        C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第22张图片

  • 编程实验:C++调用C函数

        C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第23张图片

5问题:如何保证一段C代码只会以C的方式被编译?

  • _cplusplus是C++编译器内置的标准宏定义
  • _cplusplus的意义
    • 确保C代码以统一的C方式被编译成目标文件

        C++ 深度解析教程(三)内联函数分析、函数参数的扩展、函数重载分析_第24张图片

6注意事项

  • C++编译器不能以C的方式编译重载函数
  • 编译方式决定函数名被编译后的目标名
    • C++编译方式将函数名参数列表编译成目标名
    • C编译方式只将函数名作为目标名进行编译

7小结

  • 函数重载是C++对C的一个重要升级
  • 函数重载通过函数参数列表区分不同的同名函数
  • extern关键字能够实现CC++的相互调用
  • 编译方式决定符号表中的函数名的最终目标名

你可能感兴趣的:(C++,深度解析教程,c++,开发语言,函数重载分析,函数参数的扩展,内联函数分析)