02【C++ 入门基础】标准输入输出初识/缺省参数
文章目录
- 引言
- 标准输入输出对象的使用
- 说明:
- 缺省参数
- 缺省参数分类
- 全缺省参数
- 半缺省参数
- 注意:
- 总结
引言
通过00【C++ 入门基础】前言得知,C++是为了解决C语言在面对大型项目的局限而诞生:
C语言面对的现实工程问题(复杂性、可维护性、可扩展性、安全性)
A. 我们使用C语言的输入输出(printf/scanf)的时候:
- 需要自己手动匹配类型,如果类型错误,运行崩溃!(类型不安全)
- scanf易引发缓冲区溢出“char s[10]; scanf(“%s”, s);”。(内存不安全)
- 我们自定义的一个结构体,不可以通过printf/scanf打印!(不可扩展)
C++的解决方法,就是通过面向对象的方式,将输入和输出都封装成类(istream/ostream),并在我们库中,定义出全局的标准输入输出对象(cin/cout)。
我们现在无需知道类是什么,也无需知道C++的cin/cout如何解决问题的,我们只需要记住:
- cin/cout这两个“关键字”,确实解决了以上C语言的问题(方便复习时串联思路)。
- cin/cout如何使用(先会用起来)。
B. C语言中当函数需要不同参数组合,必须创建多个名称不同但功能相似的函数:
体现了函数灵活性不足和代码冗余
// C语言处理不同参数组合
void print_int(int value);
void print_int_color(int value, int color);
void print_int_color_precision(int value, int color, int precision);// 调用时选择特定函数,
print_int(10);
print_int_color(10, RED);
print_int_color_precision(10, RED, 2);
C++用缺省参数解决这个问题。
标准输入输出对象的使用
我们的cin、cout,其实就是我们库中的一个变量,包含在我们头文件iostream中,而库中的定义实现都是被std命名空间封装好的,所以我们使用时,需要包含头文件iostream,并用命名空间使用方法,去使用它们。
#include<iostream>
// std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中
using namespace std;
int main()
{int a;cin >> a; //屏幕中输入一个数字,这个数据就会从标准输入流,“流”入变量a.cout<< a <<endl; //数据a从标准输出流,“流”出到屏幕cout<< a << a << a << a; //如果有多个数据包输出到屏幕的话,可以使用流运算继续在后面跟。return 0;
}
说明:
- 我们的cin、cout,称为标准输入输出流,“标准”的意思,就是默认面向键盘和屏幕的输入输出,也就是说我们的输入和输出都是从键盘获取和向屏幕打印的;而“流”是一种抽象概念,表示连续流动的数据序列,我们可以将数据想象成“水流”。
- cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出(就是C语言的‘\n’),他们都包含在包含< iostream >头
文件中。 - <<是流插入运算符,>>是流提取运算符,它们像是指引“水流”方向的指示牌,如果你想要变量数据流向标准输出(流向屏幕):
cout << a;
;如果你想数据从标准输入(从键盘)流向变量:cin >> a;
。 - 使用C++输入输出更方便,不需要像printf/scanf输入输出时那样手动控制变量的格式。C++的输入输出可以自动识别变量类型(其实后续我们知道都是提前一个个去匹配的)。
- 实际上cout和cin分别是ostream和istream类型的对象,>>和<<也涉及运算符重载等知识,这些知识后续才会学习,所以这里只是简单学习他们的使用。后面我们还有有一个章节更深入的学习IO流用法及原理。
注意:早期C++标准库没有命名空间概念(没有std),直接将所有功能在全局域中实现,声明在.h后缀的头文件中,使用时只需包含对应头文件即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名空间,规定C++头文件不
带.h;旧编译器(vc 6.0)中还支持<iostream.h>格式,后续编译器已不支持,因此推荐使用+std的方式。
缺省参数
缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。
缺省参数分类
缺省参数根据我们给于的缺省值个数,分为:
- 全缺省(即函数所有的参数都给上缺省值,调用该函数甚至可以一个参数都不传);
- 半缺省(即只给了一部分参数缺省值,那么调用函数时就必须传入没有缺省值的参数。)
全缺省参数
void Func(int a = 10, int b = 20, int c = 30)
{cout<<"a = "<<a<<endl;cout<<"b = "<<b<<endl;cout<<"c = "<<c<<endl;
}
//调用函数:
Func();
Func(0);
Func(0,1);
Func(0,1,2);
//因为函数的所有参数都有缺省值,所以以上四种传参都可以正确调用函数。
半缺省参数
void Func(int a, int b = 10, int c = 20)
{cout<<"a = "<<a<<endl;cout<<"b = "<<b<<endl;cout<<"c = "<<c<<endl;
}
//调用函数:
Func(0);
Func(0,1);
Func(0,1,2);
//因为函数的第一个参数没有给缺省,所以第一个参数不可以省略,只有以上三种传参可以正确调用函数。
相信我们也发现了,我们调用带缺省值的函数时,好像省略的都是参数中的尾部,这当然是因为我们的缺省值在函数定义时是从右向左给的。难道不可以只把缺省值给左边几个参数,比如:
Func(int a, int b = 10, int c );
,然后我们调用时就不传前面几个参数吗? 不可以。
声明本质是一种承诺,你没有承诺缺省值,我调用时又不主动传参,就会报错。
注意:
A. 半缺省参数必须从右往左依次来给出
因为要避免歧义:
//后面我们知道C++是允许同名函数的。
// 假如允许任意位置缺省
void Func(int a = 10, int b, int c = 20); // 非法!但假设允许Func(, 5); // 试图让 a=10, b=5, c=20:语法非法
Func(5); // 歧义:b 未指定,且不能判断 5 是给 a 还是 b?
还有一些其他更深层的原因有关(如:参数压栈顺序、和函数指针保持一致性设计、内存布局硬性要求等),不过多阐述。
B. 缺省参数不能在函数声明和定义中同时出现
虽然声明和定义两边都可以指定缺省参数,但是我们不允许两边都加,因为要避免声明和定义的缺省参数给的值不同,而导致的问题:
//a.h
void Func(int a = 10);
// a.cpp
void Func(int a = 10)
{}// 注意:如果生命与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那个缺省值。
//test.cpp
int main()
{//调用函数:Func(); //报错:“Func”: 重定义默认参数 : 参数 1
}
C. 缺省值必须是常量或者全局变量
D. C语言不支持加缺省参数(编译器不支持)
总结
- 标准输入输出是为了解决C语言类型不安全、内存不安全、不可扩展等问题。
- 标准输入输出其实就是类的对象(类是啥后面说)。
- 缺省参数是C++为了解决C语言中函数灵活性不足和代码冗余问题。
- 缺省参数只能从右向左给,且值只能给常量或者全局变量。
本文章为作者的笔记和心得记录,顺便进行知识分享,有任何错误请评论指点:)。