跟我学C++中级篇——重载问题分析之一概述

一、函数的重载

函数的重载是一个非常常见的技术应用,可以这么说,开发者即使没有写过重载的代码,但一定用重载的代码。况且只要正规学习过书本的,在学习时都会有重载机制的相关知识点。重载看上去非常简单,但实际上,在应用时会有很多的技术小陷阱,搞不好就掉了下去。轻则达不到开发的目的,重则可能引起崩溃的情况。

二、函数重载的问题

下面看一个函数重载的异常的代码:

#include <iostream>

void print(int x) { std::cout << x << std::endl; }

template <typename T> void print(T &&x) {
  print(x); // 无限递归
}

int main() {
  print(100);
  return 0;
}

上面的代码会导致栈溢出,从而引发程序的崩溃。主要原因在于100是一个右值,它会匹配print(T &&x)的右值引用,进而不断匹配此模板函数,导致无限递归,把栈耗尽,最终崩溃。其实还有很多类似的问题,在重载中需要开发者进行控制,否则极可能复现上述代码的结果。
函数重载的确定需要保证以下几个原则在确定优先级:

  1. 精确匹配(Exact Match)
    这个最好理解,完全保持一致的对应,属于最基础的应用方式
  2. 提升转换(Promotion,如 char=>int)
    如果重载中没有完全一致的,编译器则会进行一系列的转换,从而匹配相关函数。提升在转换中是一种相对安全一些的转换。不过,危险就是从此开始的。
  3. 标准转换(Standard Conversion,如 int =>double)
    这个如同上面的2一样,强制转换,会更危险一些
  4. 用户定义转换(User-defined Conversion)
    这个也比较好理解,比如用户自定义一个类默认值为int,则就形成了自定义转换
  5. 可变参数匹配(…)
    这个是相对来说比较复杂的,在所有的上述匹配都无效的情况下,才会使用这种。

一般来说,函数重载需要对函数的签名进行如下的处理,来最终确定到底使用哪个函数:

  1. 重载函数查找
    在整个编译单元中找出所有同名的函数,它包括限定查找和非限定查找,以及前面分析过的ADL查找,还有一个,就是友元函数的处理
  2. 构建相关的重载函数集
    编译器依据函数名、参数数量及类型匹配度,从当前作用域内查找出可能调用的相关目标函数 。此处要特别注意函数模板以及类模板实例化的影响。在正常情况下,普通函数的匹配优先于模板函数
  3. 可行函数分析
    对得到的重载函数集进行具体的分析,包括参数数量,参数类型等
  4. 最优匹配
    根据相关规则选取最优的函数进行调用

三、函数重载问题常见种类

函数重载在C++中是一个非常被忽视的技术细节,出现问题的情况也有很多种,主要包括:

  1. 数据类型转换的问题
  2. 模板与普通函数的匹配问题
  3. 运算符重载的问题
  4. 限定符和修饰符的重载问题
  5. 移动主义重载问题
  6. 模板特化与重载问题
  7. 默认参数的重载问题

上面的这些问题,会在后面的文章中逐一进行分析说明。

四、总结

本文算是对函数重载问题的一个整体的概述,在后面会对其各种具体的问题进行一一的分析说明。让开发者可以将其中的一些技术细节掌握的清楚,从而在处理类似问题时有据可依,也能够快速的解决在实际工程中发现的相关问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值