C++的使用

十.函数重载(重载、隐藏、覆盖)

  1. 函数重载
    • 在同一作用域下,函数名相同,参数列表不同的函数,构成重载关系。
#include<iostream>
using namespace std;

int sum(int a,int b)
{
    cout<<""<<endl;
    retrun a+b;
}

float sum(float a,float b)
{
    cout<< "" <<endl;
    return a+b;
}

int main()
{
    cout<< sum(1,9)<<endl;
    cout<< sum(1.5f,1.9f)<<endl;
}
  1. 重载实现的机制
  • C++代码在编译时会把函数的参数类型添加到参数名中,借助这个方式来实现函数重载,也就是C++的函数在编译期间经历换名的过程
  • 因此,C++代码不能调用c函数(gcc编译出的函数)

注意:如果两个函数名一样,一定会冲突

  1. extern “C”
    {

}

  • 告诉C++编译器按照C语言的方式声明函数,这样C++就可以调用C编译器编译出的函数的函数了(C++目标文件可以与C目标文件合并生成可执行程序)
  • 如果C想调用C++编译出的函数,需要将C++函数的定义用 extern “C” 来包括一下
  1. 重载和作用域

    • 函数的重载关系发送在同一作用域下,不同作用域下的同名函数,构成隐藏关系。
  2. 重载解析

  • 当调用函数时,编译器根据实参的类型和形参的匹配情况,选择一个确定的重载版本,这个过程叫重载解析。
    1. 编译器找到实参最佳的匹配函数,编译器将生成调用代码。
    2. 编译器找不到匹配的函数,会给出错误信息。
    3. 编译器找到多个匹配函数,但没有最佳函数,这种错误叫二义性。
  • 大多数情况下编译器都能立即找到一个最佳的调用版本,但如果没有,编译就会进行类型提升,这样备选函数中就可能具有多个可能调用的版本,这样就可能产生二义性错误。
  1. 确定重载函数的三个步骤

    1. 候选函数
    • 函数调用的第一步就是确定所有可调用的函数的集合(函数名,作用域),该集合就是候选函数。
    1. 选择可行函数
    • 从候选函数中选择一个或多个函数,选择的标准(参数个数相同,而且通过类型提升实参可以被隐式转换为形参)
    1. 寻找最佳匹配
    • 优先每个参数都完全匹配的方案,其次参数完全匹配的个数,在其次是浪费内存的字节数。
  2. 指针类型也会对函数的重载造成影响

    • C++函数的形参如果是指针类型,编译时函数名中会追加 Px。(x根据类型变换)

十一.默认形参

  • 在C++中函数的形参可以设置默认值调用函数,如果没有提供实参,则使用默认形参。
  • 如果形参中只有一部分设置了默认形参,则必须靠右排列。
  • 函数的默认形参是在编译阶段确定的,因此只能使用常量、常量表达式、全局变量
  • 如果函数的声明和定义需要分开,那么默认形参必须设置在声明。
  • 默认形参会对函数重载造成影响,设置默认形参时一定要慎重

十二.内联函数

  1. 普通函数调用时是生成调用指令(跳转)当代码执行到调用位置时跳转到函数所在的代码段中执行。
  2. 内联函数就把函数编译好的二进制指令直接复制到函数的调用位置。
  3. 内联函数的优点就是提高程序的运行速度(因此没有挑战,也不需要返回),但这样会导致可执行文件增大(冗余),也就是牺牲空间来换取时间。
  4. 内联分为显式内联和隐式内联
    • 显式内联:在函数前 inline(C语言C99标准也支持)
    • 隐式内联:结构、类中内部直接定义的成员函数,则该类型函数会被优化成内联函数。
  5. 宏函数在调用时会把函数体直接替换到调用位置,与内联函数一样也是使用空间来换取时间。
    • 宏函数与内联的区别?
      1. 宏函数不是真正的函数,只是代码替换,不会有参数压栈、出栈以及返回值,也不会检查参数类型,所有类型都能使用,但这样会有安全隐患。
      2. 内联函数时真正的函数,被调用时会进行传参,会进行压栈,出栈,可以有返回值,严格检查参数类型,如果想被多种类型调用需要重载。
  6. 内联适用的条件
    • 由于内联会造成可执行文件变大,并且增加内存开销,因此只有频繁调用的简单函数适合内联。
    • 调用比较少的复杂函数,内联后并不显著提高性能,不足以抵消牺牲空间带来的损失,所以不适合内联。
    • 带有递归特性和动态绑定特性的函数无法实施内联,因此编译器会忽略声明部分的inline关键字。

十三.引用

  • 引用就是取艺名。
  1. 引用的基本特性
    • 引用就是取别名,声明就是标识符为引用,就表示该标识符是另一个对象的外号。
    1. 引用必须被初始化,不存在空的引用,但有悬空引用(变量死了名还留着)。
    2. 可以引用无名对象和临时对象,但必须是使用常引用
    3. 引用不能更换目标
    4. 引用目标如果具有const属性,那么引用也必须带有const属性
    • 引用一旦完成了定义和初始化就和普通变量名一样了,它就代表了目标,一经引用终生不能再引用其他目标。
#include<iostream>

using namespace std;

int main()
{
    int a = 19;
    int& b = a;
    cout<< a << ' ' << b << endl;
}
  1. 引用型参数
  • 引用当做函数的参数能达到指针同样的效果,到不具备指针的危险,还比指针方便。
  • 引用可以非常简单实现函数间共享变量的目的,而且是否使用引用由被调用函数说了算。
  • 引用当做函数的参数还能提高传递参数效率,指针至少还需要4字节内存,而引用只需要增加一条标识符与内存之间的绑定(映射)。
#include<iostream>

using namespace std;

void func(int& num)
{
    num = 1000;
}

int main()
{
    int num = 100;
    func(num);
    cout << num <<endl;
}
  1. 引用型返回值
  • 不要返回局部变量的引用,会造成悬空引用
  • 如果返回值是一个临时值(右值),如果非要使用引用接收的话,必须使用常引用。

注意C++中的引用是一种取别名的机制,而C语言中的指针是一种数据类型(代表内存编号的无符号整数)。

  • 练习1:实现一个C++版本的swap函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值