初学C++:函数大转变:缺省参数与函数重载

大家好,这里是彩妙呀~

从C语言过渡到C++,你会发现函数不再是简单的"输入-处理-输出"结构,而是拥有了更强大的表达能力。缺省参数让你可以为函数参数设置默认值,调用时无需提供所有参数;函数重载则允许同名函数处理不同类型的参数,大大提升了代码的可读性和灵活性。这两个特性看似简单,却深刻改变了C++的编程方式------不再需要为相似功能创建不同名称的函数,而是让函数本身"理解"上下文。

理解它们的使用规则和最佳实践,是掌握C++面向对象编程的重要一步,也是你从C语言思维转向C++思维的关键转折点

目录

缺省参数

什么是缺省参数?

使用规则与限制

函数重载

总结:选择合适的设计模式

缺省参数

什么是缺省参数?

**缺省参数(Default Arguments)**是函数声明或定义时为参数指定的默认值。当调用函数时,若未显式传递对应实参,则自动采用该默认值。

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

//下面就给大家展示什么是缺省函数

void put_string(string name = "name" , string message = "Welcome back!")
{
  cout << "Hello, " << name << "!" << message << endl;

}



int main(){
     put_string();
     put_string("小明");
     put_string("小红","你好啊");
    return 0;
}

这里使用的是线上编译器:C++ 在线工具 | 菜鸟工具 (jyshare.com),大家如果有c++程序,可以在这个网站上快速运行。

运行代码后,我们可以看出:我们定义的缺省函数,在你使用他时,如果没有传递他所需的参数时,编译器会使用在其定义中的默认值:name 以及 welcome back。

使用规则与限制

缺省函数的声明分为三类:

cpp 复制代码
// 声明

//第一类:无缺省函数
void fullDefault1(int a, int b, int c);

//第二类:半缺省函数
void fullDefault2(int a, int b = 2, int c = 3);

//第三类: 全缺省函数:所有参数都有默认值
void fullDefault3(int a = 1, int b = 2, int c = 3);

//第四类:声明与定义分离 头文件(.h)中:
// 声明:指定默认值
void func3(int a = 1, int b = 2);
// 定义:不指定默认值
void func3(int a, int b) {
    // 函数体
}


// 使用示例
void fullDefault(int a = 1, int b = 2, int c = 3);

fullDefault();        // 全缺省:a=1, b=2, c=3

fullDefault(10);      // a=10, b=2, c=3

fullDefault(10, 20);  // a=10, b=20, c=3

**缺省参数的声明位置:**缺省函数在声明时如果使用了默认值,那么定义时不可以再写默认值:

cpp 复制代码
// 声明(头文件或函数前)  
void func(int a = 10);  


// 定义(不可再写默认值)  
void func(int a) { 
    /* ... */ 
}  

默认值的类型:必须是全局变量或常量表达式。

参数顺序要求 :必须从右往左连续设置默认值,不能跳过。

cpp 复制代码
// 正确:  
void func(int a, int b = 20, int c = 30);  
// 错误:  
void func(int a = 10, int b, int c = 30);  

C++要求默认参数必须从右向左连续设置,是为了避免函数调用时产生歧义

例如,若允许void func(int a=0, int b, int c),则调用func(2, 3)时,编译器无法确定是a=2, b=3还是a=0, b=2, c=3。这种设计确保了参数解析的明确性,避免了歧义。

函数重载

函数重载(Function Overloading) 允许在同一作用域内定义多个同名函数 ,但这些函数的参数列表(参数类型、数量或顺序)必须不同。在c语言中,并不支持函数重载,这个技术的引用实在c++中才实现的。

cpp 复制代码
#include <iostream>  
using namespace std;  

// 参数类型不同  
int add(int a, int b) { return a + b; }  
double add(double a, double b) { return a + b; }  

// 参数数量不同  
void print() { cout << "No arguments" << endl; }  
void print(string s) { cout << "String: " << s << endl; }  

// 参数顺序不同  
int subtract(int a, double b) { return a - (int)b; }  
int subtract(double a, int b) { return (int)a - b; }  

int main() {  
    cout << add(3, 4) << endl;         // 调用 int add(int, int)  
    cout << add(3.5, 4.2) << endl;     // 调用 double add(double, double)  
    print();                           // 输出: No arguments  
    print("Hello");                    // 输出: String: Hello  
    cout << subtract(10, 2.5) << endl; // 调用 subtract(int, double)  
}  

编译器如何区分重载函数?

C++通过**名称修饰(Name Mangling)**为每个重载函数生成唯一的符号。例如:

  • add(int, int) 可能被修饰为 _Z3addii
  • add(double, double) 可能被修饰为 _Z3adddd

链接时,编译器根据调用时的参数类型匹配正确的函数地址。

**注意:**在函数重载时,不可以只能修改返回值!

cpp 复制代码
// 错误:仅返回值不同无法重载  
int parse();  
double parse(); // ❌ 无法区分  

这是因为在编译器调用这类函数时,不可以分辨出你要调用的是哪一种函数:即存在调用歧义。

同样的,当缺省参数遇到函数重载,就像两个相似的函数容易混淆:也会存在调用歧义

cpp 复制代码
// 危险组合!可能导致歧义  
void print(int a, int b = 10);  
void print(int a);  

print(5); // ❓编译器无法确定该调用哪个函数  
print(5, 10); // 明确调第一个参数版本  

这两类时我们初学时要注意的地方,只需多加注意,即可避免。

总结:选择合适的设计模式

特性 使用场景 优点 注意事项
缺省参数 常见配置项、兼容性升级 减少重复代码 不能跳过参数设置
函数重载 类型转换、操作符扩展 统一接口设计 返回值不能区分重载

最佳实践建议

  • 对于简单接口优先使用缺省参数(如void init(int size = 100)
  • 对于需要处理多种数据类型的场景使用重载(如bool compare(T a, U b)
  • 避免过度重载导致函数职责不清

在彩妙其他博客中,如果使用到这些函数时,也会给大家讲解一下其函数在代码中的作用。

只需多加练习,这两类函数就可以手到擒来啦

相关推荐
逻极8 小时前
Rust 结构体方法(Methods):为数据附加行为
开发语言·后端·rust
小龙报8 小时前
《算法通关指南算法千题篇(5)--- 1.最长递增,2.交换瓶子,3.翻硬币》
c语言·开发语言·数据结构·c++·算法·学习方法·visual studio
yy_xzz8 小时前
Debian 系统中 Qt Creator 用 sudo 启动后权限问题
c++·qt
国服第二切图仔8 小时前
Rust入门开发之Rust 集合:灵活的数据容器
开发语言·后端·rust
今日说"法"8 小时前
Rust 线程安全性的基石:Send 与 Sync 特性解析
开发语言·后端·rust
报错小能手8 小时前
C++笔记(面向对象)定义虚函数规则 运行时多态原理
开发语言·c++·笔记
Cx330❀8 小时前
《C++ 多态》三大面向对象编程——多态:虚函数机制、重写规范与现代C++多态控制全概要
开发语言·数据结构·c++·算法·面试
_dindong8 小时前
【递归、回溯、搜索】专题六:记忆化搜索
数据结构·c++·笔记·学习·算法·深度优先·哈希算法
seabirdssss8 小时前
JDK 11 环境正确,端口未被占用,但是运行 Tomcat 11 仍然闪退
java·开发语言·tomcat