当前位置: 首页 > article >正文

C++泛型编程指南07 函数重载

文章目录

      • 1.5 重载函数模板 (Overloading Function Templates)
        • 示例:重载 `max` 函数
        • 重载解析规则
        • 特殊情况:指针和C风格字符串
        • 注意事项

当然,以下是改进和优化后的关于重载函数模板(Overloading Function Templates)的内容叙述:

1.5 重载函数模板 (Overloading Function Templates)

与普通函数类似,函数模板也可以被重载。这意味着同一个函数名可以对应多个不同的实现版本。当调用一个函数时,编译器需要根据传递的参数类型和其他因素从多个候选者中选择最合适的版本。即使在没有模板的情况下,这个过程也可能相当复杂。本节将讨论在包含模板时的重载解析规则。

示例:重载 max 函数

以下是一个简短的程序,展示了如何重载 max 函数模板:

// basics/max2.cpp

// 针对两个int类型值的最大值:
int max(int a, int b)
{
    return b < a ? a : b;
}

// 针对任意类型的值的最大值:
template <typename T>
T max(T a, T b)
{
    return b < a ? a : b;
}

int main()
{
    ::max(7, 42);              // 调用非模板函数,匹配两个int值
    ::max(7.0, 42.0);          // 调用模板函数,推断为max<double>
    ::max('a', 'b');           // 调用模板函数,推断为max<char>
    ::max<>(7, 42);            // 显式指定使用模板函数,推断为max<int>
    ::max<double>(7, 42);      // 显式指定返回类型为double
    ::max('a', 42.7);          // 调用非模板函数,允许类型转换
}

该示例展示了非模板函数可以与同名的函数模板共存,并且可以用相同的类型进行实例化。在其他条件相同的情况下,重载解析倾向于选择非模板版本。

重载解析规则
  • 精确匹配优先:如果存在一个非模板函数能够精确匹配传入的参数类型,则优先选择该函数。

    ::max(7, 42);  // 精确匹配非模板函数
    
  • 模板推导匹配:如果没有精确匹配的非模板函数,编译器会尝试通过模板推导来找到最适合的模板函数。

    ::max(7.0, 42.0);  // 调用模板函数,推断为max<double>
    ::max('a', 'b');   // 调用模板函数,推断为max<char>
    
  • 显式指定模板参数:可以通过显式指定模板参数来选择特定的模板函数版本。

    ::max<>(7, 42);             // 显式指定使用模板函数,推断为max<int>
    ::max<double>(7, 42);       // 显式指定返回类型为double
    
  • 类型转换:普通函数可以进行隐式类型转换,而模板函数则不行。

    ::max('a', 42.7);  // 调用非模板函数,允许类型转换
    
特殊情况:指针和C风格字符串

有时,您可能需要针对不同类型的参数(如指针或C风格字符串)提供专门的重载版本:

#include <cstring>
#include <string>

// 两个任意类型值的最大值
template <typename T>
T max(T a, T b)
{
    return b < a ? a : b;
}

// 指针的最大值
template <typename T>
T* max(T* a, T* b)
{
    return *b < *a ? a : b;
}

// C风格字符串的最大值
char const* max(char const* a, char const* b)
{
    return std::strcmp(b, a) < 0 ? a : b;
}

int main()
{
    int a = 7, b = 42;
    auto m1 = ::max(a, b);         // 两个int类型值的max()

    std::string s1 = "hey", s2 = "you";
    auto m2 = ::max(s1, s2);       // 两个std::string类型值的max()

    int* p1 = &b, *p2 = &a;
    auto m3 = ::max(p1, p2);       // 两个指针的max()

    char const* x = "hello", *y = "world";
    auto m4 = ::max(x, y);         // 两个C风格字符串的max()
}
注意事项
  1. 避免悬空引用:如果模板函数以引用方式传递参数,并且存在以值传递的重载版本,则可能导致悬空引用问题。

    template <typename T>
    T const& max(T const& a, T const& b)
    {
        return b < a ? a : b;
    }
    
    char const* max(char const* a, char const* b)
    {
        return std::strcmp(b, a) < 0 ? a : b;
    }
    
    template <typename T>
    T const& max(T const& a, T const& b, T const& c)
    {
        return max(max(a,b), c);  // 对于C风格字符串,可能导致悬空引用
    }
    
  2. 确保所有重载版本可见:定义函数的所有重载版本应在调用之前声明,否则可能导致意外行为。

    template <typename T>
    T max(T a, T b)
    {
        std::cout << "max<T>() \n";
        return b < a ? a : b;
    }
    
    template <typename T>
    T max(T a, T b, T c)
    {
        return max(max(a,b), c);  // 使用int类型的模板版本,因为后面的声明太迟了
    }
    
    int max(int a, int b)
    {
        std::cout << "max(int, int) \n";
        return b < a ? a : b;
    }
    
    int main()
    {
        ::max(47, 11, 33);  // 错误:使用max<T>(),而不是max(int, int)
    }
    

通过理解这些原则和示例,您可以更好地掌握如何有效地重载函数模板,并避免常见的陷阱。这不仅提高了代码的灵活性和可读性,还增强了其健壮性和维护性。


http://www.kler.cn/a/531778.html

相关文章:

  • 力扣73矩阵置零
  • RAG 与历史信息相结合
  • 浅谈《图解HTTP》
  • 鸿蒙HarmonyOS Next 视频边播放边缓存- OhosVideoCache
  • 探秘Linux IO虚拟化:virtio的奇幻之旅
  • 松灵机器人 scout ros2 驱动 安装
  • 来自谷歌新作:SFT负责记忆遵循,RL驱动泛化迁移?
  • Use-DeepSeek增效
  • 将D盘空间划分给C盘
  • 大年初六,风很大
  • 自研有限元软件与ANSYS精度对比-Bar2D2Node二维杆单元模型-四连杆实例
  • 华为OD机试E卷 --智能成绩表--24年OD统一考试(Java JS Python C C++)
  • GRN前沿:利用DigNet从scRNA-seq数据中生成基于扩散的基因调控网络
  • Linux:指令大全(二)
  • OpenAI推出Deep Research带给我们怎样的启示
  • 物业管理系统源码提升社区智能化管理效率与用户体验
  • 使用IDEA社区版搭建Springboot、jsp开发环境
  • RAG 与历史信息相结合
  • 自动化运维的未来:从脚本到AIOps的演进
  • 基于LabVIEW的Modbus-RTU设备通信失败问题分析与解决
  • 自托管看板工具BanBan
  • 利用redux与react实现异步操作
  • Mac本地部署DeekSeek-R1下载太慢怎么办?
  • 基于Spring Security 6的OAuth2 系列之九 - 授权服务器--token的获取
  • Golang 并发机制-5:详解syn包同步原语
  • 【玩转 Postman 接口测试与开发2_015】第12章:模拟服务器(Mock servers)在 Postman 中的创建与用法(含完整实测效果图)