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

C++ Qt 模板函数和函数重载

一、前言

        学到函数重载后,会遇到一个问题,多个重载函数功能相似,因为形参的不同而需要多次重复定义,写起来虽然不难,但是却会导致代码冗余。就像鸡肋一样,不定义无法完成对应参数的相同功能实现,定义了但是功能相同导致代码有点啰嗦。这个问题几乎所有使用C++的人都碰的到,那么在C++中肯定有对应解决方式,查阅资料后看到了模板函数这个机制,完美的解决了这个问题。

二、函数重载

        函数重载是C++的一项特性,允许在同一个作用域中定义多个名称相同但参数列表不同的函数。函数的调用根据参数的类型和数量来区分,从而决定调用哪个具体的函数。函数重载是C++实现多态性的一种形式,属于编译时多态(编译时绑定)。

        简单来说,函数重载只需要记住以下几点:函数名相同、参数列表不同、返回值不影响重载、默认参数注意事项(形参有默认值可能导致调用时的二义性)。简单举几个例:

//示例一 形参不同
void print(int i) {
    std::cout << "Integer: " << i << std::endl;
}
void print(double d) {
    std::cout << "Double: " << d << std::endl;
}
void print(const std::string &s) {
    std::cout << "String: " << s << std::endl;
}
//调用时
print(42);               // 调用 print(int)
print(3.14);             // 调用 print(double)
print("Hello, World!");  // 调用 print(const std::string &)

//示例二 返回值不影响
//编译时会报错,这不是函数重载
void print(int i) {
    std::cout << "Integer: " << i << std::endl;
}
int print(int i) {
    std::cout << "Integer: " << i << std::endl;
    return 1;
}
bool print(int i) {
    std::cout << "Integer: " << i << std::endl;
    return false;
}

//示例三 不同的形参存在默认值,造成错误二义性
void func(int x, double y = 3.0);
void func(int x);
//调用时
func(10); // 二义性,无法确定调用哪个版本

三、模板函数

        模板函数是C++中的一项泛型编程特性,允许编写能够处理任意类型的通用代码。通过模板函数,可以用一种通用的形式编写逻辑,而不需要为每种数据类型单独实现函数。模板函数在编译时会生成具体类型的函数实现,这种特性称为编译时多态。

        首先来看模板函数的基本语法,模板函数使用template关键字声明,使用模板参数typename T来传递参数类型,这里typename也可以使用class,下面是一个示例:

template <typename T>
T functionName(T parameter) {
    // 函数逻辑
    return parameter;
}

        在使用模板函数时,也可以使用多个模板参数,模板参数可以是一个常量值,当然作为一个函数,那就可以使用重载,就是对于一个特定的类型参数进行其他处理,在这里叫模板函数的特化,也可以和普通的函数同名重载,需要注意的是模板函数的优先级比较低,会优先调用普通函数。在调用模板参数时,有两种调用方式:编译器根据函数的参数类型自动推导模板参数、调用时显式地指定模板参数类型。下面举几个示例来说明模板参数:

//设置多个模板参数
template <typename T1, typename T2>
void print(T1 a, T2 b) {
    std::cout << "First: " << a << ", Second: " << b << std::endl;
}
//调用
print(42, "Hello");          // T1 = int, T2 = const char*
print(3.14, 42);             // T1 = double, T2 = int
print("Hello", "World");     // T1 = const char*, T2 = const char*

//使用常量来作为参数
template <typename T, int N>
T arraySum(T (&arr)[N]) {
    T sum = 0;
    for (int i = 0; i < N; ++i) {
        sum += arr[i];
    }
    return sum;
}
//调用
int arr[] = {1, 2, 3, 4, 5};
cout << arraySum<int, 5>(arr) << endl; // 显式指定模板参数

//模板函数的特化
template <typename T>
void show(T x) {
    std::cout << "Generic: " << x << std::endl;
}
// 针对const char*特化
template <>
void show(const char* x) {
    std::cout << "Specialized: " << x << std::endl;
}
//调用
show(42);             // 调用通用版本
show("Hello World");  // 调用特化版本

//模板函数与普通函数的重载
void print(int x) {
    cout << "Non-template version: " << x << endl;
}
template <typename T>
void print(T x) {
    cout << "Template version: " << x << endl;
}
//调用
print(42);    // 调用普通函数
print(3.14);  // 调用模板函数


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

相关文章:

  • 1.Nuxt学习 搭建项目 渲染页面基本操作
  • RabbitMQ的核心组件有哪些?
  • 【操作系统】每日 3 题(七十一)
  • 深度学习物体检测之YOLOV5源码解读
  • 为markdown导出的pdf添加页眉页脚
  • 分享一次接口性能摸底测试过程
  • qt 鼠标点击事件
  • Servlet学习中遇到的一些问题及解决
  • 从零开始学习 sg200x 多核开发之 sophpi 编译生成 fip.bin 流程梳理
  • docker修改容器网络
  • Cobalt Strike 4.8 用户指南-第十四节 Aggressor 脚本
  • 强化学习Q-learning及其在机器人路径规划系统中的应用研究,matlab代码
  • ubuntu禁用内核更新
  • 【Java入门指南 Day15:Java网络编程】
  • C# 如何使用多线程
  • 深入理解数据库 JOIN 操作
  • 【Tomcat】第一站:理解tomcat与Socket
  • 【面试问题】JIT 是什么?和 JVM 什么关系?
  • IDEA下加载音频文件操作
  • Linux 查看文件末尾命令 tail 详细介绍