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

七、函数重载与默认参数(Function Overloading Default Arguments)

七、函数重载与默认参数(Function Overloading & Default Arguments)

7.1 名称修饰(More name decoration)

  • 函数重载(Function Overloading): 相同的函数名,参数类型数量不同

  • 注意点:

    • 返回类型 不参与重载决议。

      int add(int,int);
      void add(int,int);//错误:重定义
      
    • 参数名不影响重载

      int add(int x, int y) { }
      void add(int a, int b) { } // 错误:重新定义(redefinition)
      
  • 示例

    //The number of arguments are different
    int min(int a,int b){return a<b ? a:b;
    }int min(int a,int b,int c){int t = min(a,b);return min(t,c);
    }void main(){cout << min(-2,8,0) << endl;cout << min(0,8) << endl;
    }
    

7.2 函数重载实例

Stash3.h

//C07:Stash3.h
#ifndef STASH3_H
#define STASH3_H
class Stash{int size;// Size of each spaceint quantity;// Number of storage spacesint next;// Next empty spaceunsigned char* storage;// Dynamically allocated array of bytesvoid inflate(int increase);
public:Stash(int size);//Zero quantityStash(int size,int initQuantity);~Stash();int add(void* element);void* fetch(int index);int count();
};
#endif STASH3_H

函数重载:

Stash(int size);//Zero quantity
Stash(int size,int initQuantity);

Stash3.cpp

//C07:Stash3.cpp
#include "Stash3.h"
#include <iostream>
using namespace std;
const int increment = 100;
Stash::Stash(int sz){size = sz;quantity = 0;next = 0;storage = nullptr;
}Stash::Stash(int sz,int iniQuantity){size = sz;quantity = 0;next = 0;storage = 0;inflate(initQuantity);
}
…………

7.3 联合体(unions)

  • struct 默认 publicclass 默认 private 。除此之外,二者几乎一样。
  • union 可包含构造函数、析构函数、成员函数。
  • unionclass 区别是:内存存储方式不同union 成员共用内存。
  • union 不能作为基类继承。

7.4 默认参数(Default arguments)

概述

  • 默认参数 是在函数声明中给定的一个值,当你在调用函数时没有提供对应的参数值,编译器会自动填入这个默认值
  • 就像函数重载一样,默认参数 允许你在不同情况下使用相同的函数名 .
  • 和函数重载不同之处在于,是用 默认参数 时,是编译器在替你填补参数值 ,而不是你手动写出多个函数版本。

例子

  • 无默认参数

    class Date{int year,month,day;
    public:Date(){year = 0;month = 0;day = 0;}Date(int y){year = y;month = 0;day = 0;}Date(int y,int m){year = y;month = m;day = 0;}Date(int y,int m,int d){year = y;month = m;day = d;}
    };void main(){Date a;Date b(2004);Date c(2004,1);Date d(2025,4,25);    
    }
    
  • 含默认参数

    class Date{int year,month,day;
    public:Date(int y = 0,int m = 0,int d =0){year = y;month = m;day = d;}
    };void main(){Date a;Date b(2004);Date c(2004,1);Date d(2025,4,25);    
    }
    
  • 函数含默认参数,声明与定义

    定义

    #include <iostream>
    using namespace std;
    void fun(int a = 1,int b = 3,int c = 5)//definition
    {cout << a << "." << b << "." << c << endl;
    }//declaration
    void main(){fun();//1,3,5fun(1);fun(1,3);fun(1,3,5);
    }
    

    声明

    #include <iostream>
    using namespace std;
    void fun(int a = 1,int b = 3,int c = 5);//declaration
    void main(){fun();//1,3,5fun(1);fun(1,3);fun(1,3,5);
    }
    void fun(int a,int b,int c){cout << a << "." << b << "." << c << endl;
    }
    

    默认参数只能写一次,写在函数声明定义 中都行,但不能写两次

规则

  • 默认参数只能从右往左提供,不能从中间跳过

    int f(int, int = 0, char* = 0);   // OK
    int g(int = 0, int, char* = 0);   // error
    

    原因:

    1. 默认参数的作用,是在调用函数时编译器自动补全你没写的参数。

      假设这样写

      void f(int a = 1, int b, int c = 3);  // ❌ 错误!void main(){f(10);
      }
      

      编译器会不知道

      • 10 是传给ab 没有值?
      • 10 是传给ba默认值1 吗?
    2. C++编译器从右往左补参数

      编译器在补默认参数时,是又右边开始一个个往左补的。所以必须保证:

      • 右边有默认参数,编译器才能往左跳。
      • 如果右边没有默认值而左边有,它就不知道从哪里开始补了。
  • 默认参数可以是字面值常量表达式

    int f();
    void delay(int k,int time = f());
    
  • 默认参数在同一作用域中只能定义一次:默认参数只能写一次,写在函数声明定义 中都行,但不能写两次

    void fun(int x = 7);
    void fun(int x = 8); // error 错误:重复定义
    

占位参数(Placeholder arguments)

  • 在函数声明中,参数可以不写参数名:

    void f1(int x,int = 0,float = 1.1);
    
  • 在函数定义中,也可以不写所有参数名:

    void f2(int x,int,float flt){}
    
  • 在上面这个函数体中,xflt 是可以使用的,但中间那个int 参数不能用,因为它没有名字(是匿名占位参数)。但是调用函数时还是必须给出这个参数的值

    f2(1, 2, 3.0);  //调用时必须写3个实参
    
  • 一般用于库开发者对外提供接口声明时的头文件,或仅作函数原型说明的场景。比如

    // 在头文件中:
    void logEvent(int, const char*);// 在 .cpp 文件中:
    void logEvent(int level, const char* msg) {cout << level << ": " << msg << endl;
    }
    

7.5 选择重载还是默认参数

  • 二者都可以提升函数调用灵活性,选择依据:
    • 效率
    • 接口设计清晰度(可复用性)
  • 如果你选择的方法能让类更简单使用和复用,那么就成功了

重载

//add.h
int add(int a,int b);//add.cpp
#include "add.h"
int add(int a,int b){return (a+b);
}
int add(int a,int b,int c){return (a+b+c);
}
//app_1.cpp
#include "add.h"
void main(){add(2,3);add(2,3,4);
}

默认参数

//add.h
int add(int a,int b,int c = 0);//add.cpp
#include "add.h"
int add(int a,int b,int c){return (a+b+c);
}//app_2.cpp
#include "add.h"
void main(){add(2,3);add(2,3,4);
}

7.6 总结

  • 函数重载:使用相同函数名,处理不同类型或数量参数。
  • 默认参数:简化函数调用,提升接口友好性。

相关文章:

  • 【Agent】LangManus深度解析:AI自动化框架的对比与langgraph原理
  • 短视频矩阵系统可视化剪辑功能开发,支持OEM
  • ASP.NET Core 自动识别 appsettings.json的机制解析
  • 2025年的营销趋势-矩阵IP
  • C 语言中实现依赖反转(Dependency Inversion Principle,DIP)
  • linux安装单节点Elasticsearch(es),安装可视化工具kibana
  • 汽车行业EDI教程——北美X12标准 需求分析及方案
  • 通过模仿学习实现机器人灵巧操作:综述(下)
  • 1.9软考系统架构设计师:优秀架构设计师 - 超简记忆要点、知识体系全解、考点深度解析、真题训练附答案及解析
  • springboot启动的端口如何终止
  • pyqt中以鼠标所在位置为锚点缩放图片
  • 初识Redis · 哨兵机制
  • Hbase集群管理与实践
  • lumen中使用JWT下getTTL令牌过期源码解析(AI)
  • 基于Docker的Flask项目部署完整指南
  • Bytebase 3.5.1 - 扩展了对数据库的连接参数支持
  • 纯HTMLCSS静态网站——元神
  • 操作指南:vLLM 部署开源大语言模型(LLM)
  • Kafka与Spark-Streaming:大数据处理的黄金搭档
  • [mysql]数据类型精讲
  • 中央政治局会议举行,传递三重确定性
  • 两部门:推动“青年驿站”为毕业生跨地区求职提供住宿优惠便利
  • 昆明一小区电梯突然从40楼降到负4楼,回应:临时断电引起
  • 电厂 | 京东、美团为什么抢着为你送外卖?
  • 美官员称与乌克兰会谈富有成效,但仍存重大分歧
  • 山西国道塌方致55岁货车司机死亡,女儿:货车的车贷还要还