导图社区 第八章函数探幽
C 自学笔记 第八章函数探幽,整理了C++内联函数、引用变量、默认参数、函数重载 (函数多态)、函数模板(通用编程)的知识,快来看看。
编辑于2023-04-13 09:08:22 广东第八章 函数探幽
1. C++内联函数
1. 性质
1. 不同于常规函数的地方
1. 编译器将相应的函数代码代替函数调用
2. 即不用跳到另外一个位置执行代码,再跳转回来
3. 代价是使用更多内存
1. 故使用时,用占内存较小的函数
4. 也是按值传递
2. 使用
1. 声明前加上关键字inline
2. 定义前加上关键字inline
3. 通常省去原型,将定义直接放在原本放原型的地方
2. 引用变量
1. 性质
1. 引用是已定义变量的别名
2. 引用变量的主要用途是用作函数的形参
3. 通过将引用标量作为参数,函数将使用原始数据,而不是其副本
2. 创建引用变量
1. 使用 & 符号
1. 表示为指向某类型的引用
2. 在声明引用变量时必须进行初始化
2. & 不是地址运算符 , 而是类型表示符
3. 在创建引用后,int& rodent = rats;
1. 两个变量的值和地址均相同
2. rodent++会使两者同时+1
3. 将引用作为函数参数
1. 按引用传递
2. 可进行交换数值的方法
1. 指针
2. 引用
1. 传入函数时,函数的引用函数将被初始化为函数调用传递的实参
3. 函数直接按值传递是不能修改原始数据
4. 引用的属性和特别之处
1. 按值传递与按引用传递的区别
1. 按值传递的函数,可使用多种类型的实参
2. 按引用传递的函数,传递的引用很严格
不能将表达式如 (x+3)赋给函数,因为它不是变量
2. 临时变量、引用参数和const
1. 当引用参数为const时
1. 如果实参和引用参数类型不匹配,c++将生成临时变量(注意const为前提)
2. 条件
A. 实参类型正确,但不是左值
B. 实参类型不正确,但可以转化为正确类型
C. 左值指的是能被引用的数据对象
3. 这些临时变量只在函数调用期间存在,而后编译器随意删除
4. 注意如果产生了临时变量,原数据将不会被改变
2. 尽可能多使用const
A. 可以避免无意中修改数据的编程错误
B. 能够处理const和非const实参,否则将只能接受非const数据
C. 使用const引用可以使函数正确生成临时变量
5. 将引用用于结构
1. 性质
1. 如果返回值为结构类型 而不是 结构类型的引用
1. 则在函数套叠时,将按值传递而不是按引用传递,数据将不会被更改
2. 为何返回引用
若按值传递,程序将值复制到一个临时的位置,后续调用程序将使用这个值
dup = accumulate(team,five)
若按值传递,则将得到的结构复制到一个临时位置,后再将这些拷贝复制给dup
若按引用传递,则相对于直接把team复制到dup,效率更高
3. 返回引用时需要注意的问题
避免返回函数终止时不再存在的内存单元引用
解决办法
返回一个作为参数传递给函数的引用
或使用new来分配新内存
4. 为何将const用于引用返回类型
若返回的引用类型不想被修改,就使用const类型
6. 引用特殊应用
1. 将引用用于类对象
1. 同上,注意返回的是引用类型还是值
如果返回的引用类型,则需要注意返回的引用是谁的引用,如果是临时变量的引用则非法
如果返回的是值,请注意是按值传递,则在后面的计算中,原值不做改变
2. 图
7. 对象、继承和引用
性质
1. 继承
1. 能够将特性从一个类传递给另外一个类的特性
派生类
ostream是基类而ofstream是派生类
2. 基类引用可以指向派生类对象,而无需强制类型转换
2. P223
8. 何时使用引用作为参数
性质
引用参数能修改函数中的数据对象
通过引用传递而不是整个数据对象,提高程序运行速率
选择
数据对象是数组,只能使用指针
数据对象是结构,则均可以使用
数据对象是类对象
使用引用
3. 默认参数
1. 性质
默认参数
函数调用时省略实参,并自动使用了一个值
2. 方法
通过函数原型总结编写
必须从右向左依次添加默认值
4. 函数重载 (函数多态)
1. 性质
函数重载的关键是函数的参数列表——函数特征标
参数数目
参数类型
注意一个特点(类型引用和类型本身视为一个特征标)
若仅返回类型不同,所定义的函数仍然发生错误,视为非法
在使用函数重载时
需要在函数调用中采用正确的参数类型
若都没有与之相应的函数,将自动寻找最匹配的版本
2. 重载示例
基本当函数执行相同的任务时,但使用不同种类的数据时,采用函数重载
5. 函数模板(通用编程)
1. 性质
通用的函数描述
允许使用任意类型来完成这一过程
使用泛型来定义函数
2. 使用函数模板
建立函数模板,关键字 template 和 typename是必须的
也可以用class代替typename
类型命名 Anytpye 或任意 T之类的
注意不一定所有的参数都是模板
必须使用尖括号 <>
3. 重载的模板
图
4. 模板的局限性
模板某时候可能并不能适配所用数据类型
解决方法
显示具体化
5. 显示具体化 (还是模板函数的一种)
性质
当编译器找到与函数调用匹配的具体化定义时,将使用该定义而不再寻找模板
具体化示例
template <>void Swap<job>(job& j1, job& j2);
有尖括号
只有当参数输入时才创建相应的函数定义
6. 实例化与具体化
性质
隐式实例化
函数模板并不会生成函数定义,而是根据得到参数类型来生成模板实例
显示实例化
直接命令编译器创建相应的函数定义
template void Swap<int>(int j1, int j2);
无尖括号
无论是否有参数输入,都创建相应的函数定义
不能与具体化示例同时使用
在调用时Swap<int>(int j1, int j2);
调用时也加入尖括号,并加入数据类型
会使参数的数据类型作一个强制类型转换
P241
7. 编译器将使用哪个函数版本
重载解析
创建候选函数列表
使用函数列表创建可行函数列表
确定是否使用最佳的可行函数
完全匹配,但常规函数优于模板函数
提升转换
标准转换
用户定义的转换
完全匹配与最佳匹配
P237
将寻找最匹配的函数
创建自定义选择
在使用非模板函数,模板函数时,加入<>后,表明这里要使用模板而不是非模板函数
并且尖括号内可添加需要强制转换的类型
8. 函数模板的发展
p243
decltype
声明返回的数据类型
后置返回类型
具体化
1. 具体化示例
2. 隐式实例化
3. 显示实例化
5
3
函数
1. 非模板函数
2. 模板函数
3. 显示具体化函数
1. 及他们的重载版本
4. 顺序
具体化>>常规模板 ,非模板函数 >> 具体化和常规模板