C++PrimerPlus第八章

内联函数

函数前面加inline就是内联函数:

内联函数会直接代替函数调用,出现在程序当中,不会有函数调用的过程。

内联函数的函数原型和函数定义放在一起,通常只有一行。

内联函数以值进行调用和返回。与C的宏定义不一样,C宏定义是原封不动的将表达式等放在宏的地方。

引用变量(伪装指针)

引用要求在定义的时候初始化

引用变量等价于:

int &a = rats;
int * const ps = &rats;
a与*ps相同

特殊操作:(可以作用于指针,但是不能用在表达式上)

int rats;
int *ps = &rats;
int &a = *ps;
// 此时a也是rats的引用

引用传递用于结构和类。不使用在基本变量上。

可以使用const double &a = b;保证引用不会修改原始值。

临时变量生成条件:(临时变量在函数结束的时候释放)

  1. 函数使用引用传递
  2. const引用(const引用保证不修改原值,因为临时变量不会对原值产生影响)
  3. 1.类型正确的非左值 2.类型不正确的左值。

临时变量和值传递操作相同,所以有的编译器会进制使用临时变量。

左值:可以引用的量:变量,数组元素,结构成员,指针,解引用指针。有地址

右值:字面值(除了字符串字面值),表达式。没有地址

尽量使用const的原因:

  • const让实参既可以是const也可以是非const
  • 保证数据不会被随意更改
  • 可以使用临时变量

右值引用:应用在语义移动中。int && a;

函数的返回引用操作:返回的引用最好是输入到函数当中的引用。

常规函数的返回值是右值。

const string引用可以传递C风格字符串。

类对象的引用:ofstream是ostream的派生类。ostream是基类。

使用基类的引用设置函数参数:可以引用派生类和基类。

cout.setf(ios_base::fixed,ios_base::showpoint)
fixed是定点表示
showpoint是小数点后的0显示出来
cout.precision() // 小数点后,有效位数
ios_base::fmtflags 一种类型cout.setf()的返回类型,可以保存之前所有的setf配置,用于恢复

一个建议:

基础类型值传送,如果需要修改。使用指针

数组一定使用指针

结构使用指针或引用

类对象使用引用

默认参数放置在函数原型的定义当中。(实参从左到右依次赋值,默认参数从右向左依次给值)。

函数重载和函数多态一个意思:

多态指函数具有多个形态。重载是指有多个同名的函数。

函数重载:函数与函数之间的区分是特征标(即函数的参数列表)。

对于函数重载:

  • int a和int &a等价
  • const和非const带有指针和引用时有区别

对于const和非const优先匹配完全相同的情况。

对于unsigned int 和 int, long,long long之间没有远近,所以会出现二义性。

函数重载:只有在实现相同操作但是对于不同数据类型的时候,使用函数重载。

名称修饰,名称矫正:是针对编译器而言的一种变形,利于编译器识别不同的重载函数。

泛型编程也可称为通用性编程,其特性可以叫做参数化类型。

模板经常放在头文件当中:使用时调用头文件。

泛型编程:也有原型,定义,调用(生成)

template <typename T>
void swap(T &a,T &b);
// 原型
template <typename T>
void swap(T &a,T &b)
{
}
// 定义
swap(a,b);
// 使用

模板并不会被加入到可执行程序中,只有生成的函数在程序中。

对于swap交换操作:对于数组无法实现。(针对类似的问题)提出了显示具体化。得到具体化函数:

template<> void swap(job &a,job &b);
// job是一个结构

优先级:常规函数,具体化函数,模板函数.

实例化和显示具体化:

显示实例化和隐式实例化,显示具体化都是具体化。因为他们都生成了函数定义。

由于模板本身并不是定义,只有当调用的时候,编译器才会生成定义,这时是一个实例化的过程。但是是一种隐式实例化。

显示实例化:template void swap<int>(int ,int)

swap<double>(a,b)

显示具体化:template<> void swap<int>(int,int)

template<> void swap(int,int)

函数参数中:类型和非const引用不能强制转化。

重载解析:判断函数的优先级。

1.找到参数个数相同的函数或模板

2.去除类型不符合要求的。(强制转换可以也行)

3.按标准寻找。

  • 完全匹配(常规>具体化模板>模板)不考虑const。
  • 提升转换(short,char->int,float->double)
  • 标准转换(int->char,long->double)
  • 用户自定义转换

等价的情况,符合完全匹配要求但是参数类型不同的情况:1+3:1数组的情况。3是否有const,是否有volatile,是否有&引用.

只有两种情况完全匹配不会产生二义性ambiguous:

1.const起到区分作用只有当:指针和引用时成立

2.一个是模板函数,一个是常规函数,一个是显示具体化函数或者两个模板函数。(带有模板函数的情况,找出最具体的模板)

找最具体模板的规则:函数模板的部分排序规则。 

通过调用方法来选择最优的匹配情况:

swap<>(a,b)  <>暗示使用模板

swap<int> (a,b)显示实例化也是用模板

对于多参数的函数:如果一个比另一个强:则必须所有的参数匹配程度不低于另一个,且有一个比另一个高,此时才能说明一个比另一个更匹配。

针对以下问题:

template <typename T1,typename T2>
void swap(T1 x, T2 y)
{
    xps = x + y;
}  // xps的类型无法判断
int x, double y  则是double
short x,char y  则是int

解决方法:使用decltype(x+y) xps

decltype(expression)判断方法:1.单独的标识符,则与表示符类型相同。2.函数返回则与返回类型相同。

3.如果是左值,则左值类型的引用 4.都不满足则与expression同类型

问题2:

???? swap(T1 x, T2 y)
{
    return x + y;
}
// 此时由于函数的返回值位置未定义x和y,不能使用decltype
// 引入后置返回类型
auro swap(T1 x, T2 y) -> decltype( x + y)

总结:重载解析:

1. 确定有没有自定义要求

2. 找到匹配的函数,利用函数的4个标准判决。

3. 找到匹配的模板,利用模板的部分排序规则实现

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值