跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++

C++ 入门:输入输出、缺省参数与函数重载

C++ 输入输出流基于 iostream 头文件,提供 cin/cout 对象及流操作符,支持类型自动识别与自定义类型扩展,需注意 endl 与 \n 的缓冲区差异及性能优化。缺省参数允许函数调用时省略部分实参,遵循从右向左缺省规则。函数重载利用参数数量、类型或顺序的差异实现同名函数多态,但返回值类型不参与重载判定。

t ag发布于 2026/3/29更新于 2026/10/2282 浏览
C++ 入门:输入输出、缺省参数与函数重载

C++ 的输入与输出

在 C 语言时代,我们依赖 printf 和 scanf 完成输入输出,需要手动指定格式符,处理类型不匹配的风险是每个开发者的日常。而 C++ 带来了全新的 IO 库,以类型安全、可扩展的设计重构了输入输出的体验。

核心载体: 头文件

<iostream> 是 Input Output stream 的缩写,作为 C++ 标准输入输出的核心头文件,它不仅定义了 cin, cout, endl 等标准 IO 对象,同时封装了底层 IO 操作的复杂逻辑,让开发者无需关注缓冲区管理、设备交互等细节。

这里有一个值得注意的细节:在 Visual Studio 编译器中,<iostream> 会间接包含 <stdio.h>,因此可以混用 cin 与 scanf。但这仅适用于微软编译器,跨平台兼容性较差,建议编写代码时尽量避免混用。

核心的 IO 对象:cin 与 cout

std::cin 标准输入流

std::cin 是 istream 类的对象,主要面向窄字符(char 类型)的标准输入流。它从键盘或其他输入设备获取数据,通过流提取运算符 >> 完成数据的读取。

#include <iostream>

int main() {
    int age;
    std::cout << "请输入你的年龄:";
    std::cin >> age; // 从标准输入读取整数
    std::cout << "你的年龄是:" << age << "岁" << std::endl;
    return 0;
}
std::cout 标准输出流

std::cout 是 ostream 类的对象,同样是面对窄字符的标准输出流。它通过流插入运算符 << 向屏幕或其他输出设备写入数据,支持链式调用。

#include <iostream>

int main() {
    std::cout << "Hello, C++ IO Stream!" << std::endl;
    return 0;
}

流操作符:<< 与 >> 的双重身份

在 C 语言中,<< 与 >> 分别代表左移/右移运算符。而在 C++ 中,通过重载函数技术,这两个运算符被赋予了新的角色:

  • <<:流插入运算符,用于向输出流写入数据
  • >>:流提取运算符,用于从输入流提取数据

这种重载实现了'语法糖'效果,让 IO 操作更符合直觉。同时,运算符的返回值是流对象本身,支持链式调用:

std::cout << "姓名:" << "张三" << ",年龄:" << 25 << std::endl;

链式调用的底层原理是:每次 << 操作返回 ostream&,使得后续操作可以直接作用于同一个流对象。

换行与缓冲区:endl 的应用

初学者常误以为 endl 只是换行符,其实不然,其作用远不止于此:

  • 表面功能:相当于插入换行符 \n,实现文本换行
  • 深层功能:强制刷新输出缓冲区,将缓冲区的数据立即写入输出设备

这与直接使用 \n 有着显著的区别:

// 仅换行,不刷新缓冲区,性能更优
std::cout << "Hello\n";

// 换行 + 刷新缓冲区,适用于需要立即输出的场景(如调试日志)
std::cout << "Hello" << std::endl;

频繁使用 endl 会导致缓冲区频繁刷新,降低 IO 的性能。在性能高敏感的场景中,应当优先使用 \n,仅需要在立即输出的时候使用 endl。

C++ IO 的核心优势:从手动格式到自动适配

自动识别类型

在 C 语言中,使用 printf() 需要手动指定格式符,如 %s %d %f 等,一旦格式符与变量类型不相同,就会导致未定义行为。C++ IO 流则是通过函数重载实现了自动类型识别:

int num = 42;
double pi = 3.14;
std::string name = "C++";
std::cout << num << " " << pi << " " << name << std::endl;
// 自动识别类型,输出:42 3.14 C++

这种设计不仅简化了代码,还从根本上避免了格式不匹配的问题。

自定义类型支持

C++ IO 流的最大优势之一是支持自定义类型的输入输出。通过重载 << 和 >> 运算符,我们可以让自定义类/结构体像内置类型一样直接参与 IO 操作:

#include <iostream>

struct Point {
    int x, y;
};

// 重载<<运算符,实现 Point 类型的输出
std::ostream& operator<<(std::ostream& os, const Point& p) {
    return os << "(" << p.x << ", " << p.y << ")";
}

int main() {
    Point p{10, 20};
    std::cout << "点的坐标:" << p << std::endl;
    // 输出:点的坐标:(10, 20)
    return 0;
}

这种可扩展性让 C++ IO 流成为面向对象编程的理想选择。

面向对象的底层支撑:IO 流的设计思想

C++ IO 流的设计深度融合了面向对象的核心思想:

  • 继承体系:istream 和 ostream 作为基类,派生出文件流 (fstream)、字符串流 (sstream) 等子类,实现了 IO 操作的统一接口
  • 多态与重载:通过运算符重载和虚函数,实现了不同类型数据的 IO 适配
  • 封装性:底层缓冲区管理、设备交互等细节被封装在流内部,开发者只需要关注高层接口

这些设计使得 IO 流库既灵活又易于拓展,但也意味着需要掌握更多面向对象知识才能深入理解其底层应用原理。

提高输入输出效率

在需要输入输出性能的地方,C++ 默认配置下可能不如 C 语言高效。想要让 C++ 的输入和输出像 C 语言一样快,可以在代码开头加上这段优化代码:

ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);

C++ 的缺省参数

缺省参数的定义及其基本用法

缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。

#include <iostream>

void Func(int a = 10) {
    std::cout << a;
}

int main() {
    int a = 20;
    Func(a); // 传入参数,使用传进来的值
    return 0;
}

如果不将 a 的值传进去,结果会怎样?

#include <iostream>

void Func(int a = 10) {
    std::cout << a;
}

int main() {
    Func(); // 不传参数,使用缺省值
    return 0;
}

总结来说,我们在定义一个函数时,如果给里面的参数进行了初始化,那么在主函数调用时,如果给函数传进了参数,那就使用传进来的参数;如果没有传参数,那就使用在函数定义时所设定的初始值。

全缺省与半缺省

全缺省

全缺省顾名思义就是函数中全部参数都给了缺省值。

#include <iostream>

void Func(int a = 10, int b = 20, int c = 30) {
    std::cout << a << " " << b << " " << c << std::endl;
}

int main() {
    Func(); // 所有参数都不传,使用缺省值
    Func(1); // 只传第一个
    Func(1, 2); // 只传前两个
    return 0;
}

既然是全缺省,那是不是可以所有参数都不传进去?确实可以。这时候又有读者可能会问,能不能只传部分参数的值进去?比如只传第一个和第三个?写成 Func(a, , c) 显然是不行的,因为在制定语法的时候这是不被允许的。如果我们真的只想传第一个和第三个的值,可以调换一下位置:

#include <iostream>

void Func(int a = 10, int c = 30, int b = 20) {
    std::cout << a << " " << b << " " << c << std::endl;
}

int main() {
    Func(1, 3); // 只传入 a 和 c 的值
    return 0;
}

这样一来,只有 a 和 c 的值被修改了。需要注意的是,在传入值的时候,只能从左向右依次传值,不能跨越地、间隔跳跃地传值。

半缺省

与全缺省相反,半缺省就是对函数中部分变量进行初始化,其中规定只能从右往左依次缺省,不能间隔跳跃缺省。

#include <iostream>

void Func(int a, int b, int c = 10) {
    std::cout << a << " " << b << " " << c << std::endl;
}

int main() {
    Func(1, 2); // 必须传入前两个参数
    return 0;
}

如果想要让两个参数缺省,那就这样子写:

#include <iostream>

void Func(int a, int b = 20, int c = 10) {
    std::cout << a << " " << b << " " << c << std::endl;
}

int main() {
    Func(1); // 只传入 a
    return 0;
}

注意:带缺省参数的函数调用,C++ 规定必须是从左到右依次给实参,不能跳跃给实参。函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,这时候规定必须是函数声明时给缺省值。


C++ 的函数重载

在 C 语言中,我们经常碰到这样的问题:写很多个功能相同的函数但是命名却不能相同,这样就导致了程序员在编写代码时的效率大幅度降低。而 C++ 的函数重载就是为了解决这个问题。

函数重载的定义

C++ 支持在同一作用域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者类型不同。这样 C++ 函数调用就表现出了多态行为,使用更灵活。C 语言是不支持同一作用中出现同名函数的。

#include <iostream>

// 参数类型不相同
int add(int a, int b) {
    std::cout << "int (a+b) " << a + b << std::endl;
    return a + b;
}

double add(double a, double b) {
    std::cout << "double (a + b) " << a + b << std::endl;
    return a + b;
}

// 参数个数不相同
int add2(int a, int b, int c) {
    std::cout << "int (a + b + c) " << a + b + c << std::endl;
    return a + b + c;
}

int add2(int a, int b, int c, int d) {
    std::cout << "int (a + b + c + d) " << a + b + c + d << std::endl;
    return a + b + c + d;
}

// 参数类型顺序不同
void add3(int a, double b) {
    std::cout << "int a, double b" << std::endl;
}

void add3(double b, int a) {
    std::cout << "double b, int a" << std::endl;
}

int main() {
    int a = 10, b = 20, c = 30, d = 40;
    double a2 = 1.2, b2 = 2.2;
    add(a, b);
    add(a2, b2);
    add2(a, b, c);
    add2(a, b, c, d);
    return 0;
}

小贴士:返回值的不同不能作为重载条件,因为如果是同名函数的话,编译器不能区分调用哪个:

#include <iostream>

int fxx() {
    std::cout << "int fxx()" << std::endl;
}

void fxx() {
    std::cout << "void fxx()" << std::endl;
}

int main() {
    fxx(); // 编译错误:无法区分调用哪个
    return 0;
}

但是也要小心缺省函数带来的类似返回值不同的效果:

#include <iostream>

void fxx(int a) {
    std::cout << "fxx(int a)" << std::endl;
}

void fxx() {
    std::cout << "fxx()" << std::endl;
}

int main() {
    fxx(); // 这就是缺省参数带来的类似返回值不同的效果
    return 0;
}

掌握这些基础特性,能让你的 C++ 代码更加简洁、健壮且易于维护。

目录

  1. C++ 的输入与输出
  2. 核心载体:<iostream> 头文件
  3. 核心的 IO 对象:cin 与 cout
  4. std::cin 标准输入流
  5. std::cout 标准输出流
  6. 流操作符:<< 与 >> 的双重身份
  7. 换行与缓冲区:endl 的应用
  8. C++ IO 的核心优势:从手动格式到自动适配
  9. 自动识别类型
  10. 自定义类型支持
  11. 面向对象的底层支撑:IO 流的设计思想
  12. 提高输入输出效率
  13. C++ 的缺省参数
  14. 缺省参数的定义及其基本用法
  15. 全缺省与半缺省
  16. 全缺省
  17. 半缺省
  18. C++ 的函数重载
  19. 函数重载的定义

更多推荐文章

查看全部
  • C++ 网络模块兼容性优化的 7 个关键步骤
  • Linux GCC/G++编译器:从源码到可执行文件的全流程解析
  • Seedance 2.0 实测:影视级 AI 视频生成的商业化落地
  • 网络安全入门:黑客必须掌握的核心技术
  • Linux 命令行核心实战:Git 提交、权限控制与常用快捷键
  • 从零手搓中文大模型 Day04:模型参数配置和训练启动
  • 八种常见排序算法详解与实现
  • Paper Minecraft V3.0 下界更新:基于 C++ 的 2D 控制台版我的世界实现
  • Java 后端转 Web3 实战路线图
  • 基于 OpenCASCADE 的分层截面几何体重建与 STL 导出
  • Harness Engineering:AI Agent 时代软件工程的范式转变
  • 飞算 JavaAI 插件使用体验与功能分析
  • 算法题:接雨水问题详解与动态规划解法
  • 大型语言模型结构分类详解
  • 大模型时代企业转型:RAG 技术的演进与实践挑战
  • C++ 异常处理机制:异常捕获、自定义异常与实战应用
  • Go 语言信用卡号码 Luhn 算法校验实现
  • RTX50 系显卡与 CUDA、PyTorch、Python 版本对应关系整理
  • Python 学习资源推荐:Real Python 平台使用指南
  • Linux 序列化与反序列化原理及自定义网络协议实现

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online