C++_1:缺省参数(2/3)

闲话少叙,咱们这章来说说缺省参数。

何为缺省参数?

先请诸位来看一段代码:

//缺省参数
#include <iostream>
using namespace std;
void Fun(int a = 10)//此处为函数的定义,这里形参a给了一个缺省值10
{
    cout << a << endl;//此处想要实现打印a的值
}
int main()
{
    Fun();//当不传参的时候结果是什么?
    Fun(100);//传个实参过去,打印结果是多少呢?
    return 0;
}

你可能有些奇怪,诶,这个在int a = 10这个赋值行为怎么出现在了函数的参数列表,竟然还没有报错。

咱们再来看运行截图:

接下来就听老夫给各位说道说道:缺省参数。

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

void Fun(int a = 10)//此处为函数的定义,这里形参a指定了一个缺省值10
{
   // 形参a此时就是缺省参数
   //...
}

可以见得,缺省参数——一个形参,有缺省值——合起来,一个有缺省值的形参。

那我们调用这种有缺省参数的函数时:

 Fun();//当不传参的时候,形参使用缺省值
 Fun(100);//传个实参过去,形参使用实参值(传值调用嘛)
#include <iostream>
using namespace std;
void Fun(int a = 10)
{
    cout << a << endl;//此处想要实现打印a的值
}
int main()
{
    Fun();
    Fun(100);
    return 0;
}

根据Fun函数的定义,最后调用的结果,不传参的函数打印缺省值10,传实参值过去的函数打印实参值100;

缺省参数分为全缺省和半缺省参数

全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值。C++规定半缺省参数必须从右往左 依次连续缺省,不能间隔跳跃给缺省值
//全缺省
void FunAll(int a = 10,char b = 'b', int c = 100)//这种全部形参都有缺省值,之谓全缺省
{
    std::cout << a << " " << b << " "<< c << " " << std::endl;//此处想实现所有参数的打印
}
//半缺省
void FunPart(int a,char b = 'x',double c = 3.14)//不是所有参数都有缺省值(此处a没有),之谓半缺省
{
   //...
}

你要写全缺省,那没毛病,函数定义时全部形参给上一个缺省值。但说要写半缺省,你就要考虑很多了:

这第一点,就得从右往左给,不得跳跃,就比如第二段代码,就不能写成这样:

//半缺省
void FunPart(int a = 10,char b = ‘x’,double c)//教科书错误示范1——从左往右给
{
   //...
}

“默认实参不在形参列表的结尾”,编译器编着编着发现:好小子,让你从右边开始给参数。结果左边有,反而右边开头还没有,直接报错。

void FunPart(int a = 10, char b, double c = 3.14)//教科书错误示范2——跳跃间断给
{
    //...
}

这回编译器检查半缺省,还是从右往左检查,发现左右都有缺省,中间竟然没有,二话不说又给报错。

所以,写好半缺省,不二法门是什么? 从右边开始写,一旦不写,后面都不写。

void FunPart(int a, char b, double c = 3.14)//从c开始写
{
    //...
}

函数调用:从左往右 

带缺省参数的函数调⽤,C++规定必须从左到右依次给实参,不能跳跃给实参。

看到这儿,初入C++的小伙伴不禁曰一句:哥们你玩儿我呢?其实非也非也。
其实你自己想想,自己给实参从左往右这个顺序,其实发现自己是可以理解的。不理解的,发现原
来是上面给缺省值要从右往左给。
这余秋雨先生在《行者无疆》中曾道:“看似不合常理的背后,往往有着深刻的逻辑。”

 其实,这两句合起来,反而更好理解:正是基于传实参给形参是从左至右,如果需要三个参数,你只给俩,最右边的,自然而然就可以使用它的缺省值。

自然,你一个实参也不传,三个形参就只好用自己的缺省值。

反过来:给缺省值,如果从左向右给,在函数调用时,你也只传俩。从左往右录入给形参(这是原则),此时,你让第三个形参如何是好?定义时没给它缺省值,调用又忽略它。

编译器随迟但到,函数调用处给你报个“参数太少”的错。

故此,为了避免这种情况,从右至左给缺省值似乎也说得通了,编译器也直接落实从右至左检查缺省值。——以上解释,纯属博主猜想,希望随着博主日渐学习和思考过程中,能更加贴近其中奥妙,不过,咱们刚学C++,多思考一点,总是没错的。

函数声明和定义分离

函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省值。

看咱们前面写的函数,声明和定义并未分离:
//缺省参数
#include <iostream>
using namespace std;
void Fun(int a = 10)
{
    //...
}
int main()
{
    //...
    return 0;
}

而声明和定义分开是这样写的:

void Fun(int a = 20);//规定在声明里面给缺省值

int main()
{
    FunAll();
    return 0;
}
void Fun(int a)
{
  //...
}

虽说是规定,但咱们也不是不可以尝试着理解。依在下看,此计可谓“先声夺人”。

在函数定义时,反而与普通函数无二。况且,看了前面,就发现,缺省值其实可用可不用:在不传实参的情况下有用,其实大部分情况你既然设置了参数,都会有意识传参。缺省值,似乎是给形参提供了下限。这样在声明里给上缺省值,而在定义里不写缺省值,保证函数定义和原来函数差不多,而缺省值又在声明里醒目,提醒你缺省值有了,你尽管在函数定义里写。


缺省值的作用:

在应对传实参不确定时,缺省值有奇效。

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
注意:由于上传大小限制,此电子书分为两个压缩包,此压缩包part1为第一部分,需下载part2后同时进行解压!!!! 《Visual C++2010入门经典(第5版)》:使用visual C++ 2010支持的两种C++语言技术讲述C++编程的基础知识。 分享c++程序的错误查找技术,介绍程序调试的通用准则。 讨论每一个windows应用程序的结构和基本元素。 举例说明如何用mfc开发本地windows应用程序。 指导读者用C++C++/Cli设计和创建具体的windows应用程序。 提供了大量可以工作的示例和练习,旨在帮助读者掌握编程技巧。 目录 第1章 使用visual c++ 2010编程 1 1.1 .net framework 1 1.2 clr 2 1.3 编写c++应用程序 3 1.4 学习windows编程 4 1.4.1 学习c++ 4 1.4.2 c++标准 5 1.4.3 属性 5 1.4.4 控制台应用程序 5 1.4.5 windows编程概念 6 1.5 集成开发环境简介 7 1.5.1 编辑器 8 1.5.2 编译器 8 1.5.3 链接器 8 1.5.4 库 8 1.6 使用ide 8 1.6.1 工具栏选项 9 1.6.2 可停靠的工具栏 10 1.6.3 文档 11 1.6.4 项目和解决方案 11 1.6.5 设置visual c++ 2010的选项 23 1.6.6 创建和执行windows应用程序 23 1.6.7 创建windows forms应用程序 26 1.7 小结 27 1.8 本章主要内容 28 第2章 数据、变量和计算 29 2.1 c++程序结构 29 2.1.1 main()函数 36 2.1.2 程序语句 36 2.1.3 空白 38 2.1.4 语句块 38 2.1.5 自动生成的控制台程序 39 2.2 定义变量 40 2.2.1 命名变量 40 2.2.2 声明变量 41 2.2.3 变量的初始值 42 2.3 基本数据类型 42 2.3.1 整型变量 43 2.3.2 字符数据类型 44 2.3.3 整型修饰符 45 2.3.4 布尔类型 46 2.3.5 浮点类型 46 2.3.6 字面值 47 2.3.7 定义数据类型的同义词 48 2.3.8 具有特定值集的变量 49 2.4 基本的输入/输出操作 50 2.4.1 从键盘输入 50 2.4.2 到命令行的输出 50 2.4.3 格式化输出 51 2.4.4 转义序列 52 2.5 c++中的计算 54 2.5.1 赋值语句 54 2.5.2 算术运算 55 2.5.3 计算余数 59 2.5.4 修改变量 60 2.5.5 增量和减量运算符 60 2.5.6 计算的顺序 63 2.6 类型转换和类型强制转换 64 2.6.1 赋值语句中的类型转换 65 2.6.2 显式类型转换 65 2.6.3 老式的类型强制转换 66 2.7 auto关键字 66 2.8 查看类型 67 2.9 按位运算符 67 2.9.1 按位and运算符 68 2.9.2 按位or运算符 69 2.9.3 按位eor运算符 71 2.9.4 按位not运算符 71 2.9.5 移位运算符 71 2.10 lvalue和rvalue 73 2.11 了解存储时间和作用域 74 2.11.1 自动变量 74 2.11.2 决定变量声明的位置 76 2.11.3 全局变量 77 2.11.4 静态变量 80 2.12 名称空间 80 2.12.1 声明名称空间 81 2.12.2 多个名称空间 82 2.13 c++/cli编程 84 2.13.1 c++/cli特有的基本数据类型 84 2.13.2 命令行上的c++/cli输出 87 2.13.3 c++/cli特有的功能—— 格式化输出 88 2.13.4 c++/cli的键盘输入 91 2.13.5 使用safe_cast 92 2.13.6 c++/cli枚举 92 2.14 查看c++/cli类型 96 2.15 小结 97 2.16 练习 97 2.17 本章主要内容 98 第3章 判断和循环 101 3.1 比较数据值 101 3.1.1 if语句 102 3.1.2 嵌套的if语句 104 3.1.3 嵌套的if-else语句 107 3.1.4 逻辑运算符和表达式 109 3.1.5 条件运算符 112 3.1.6 switch语句 113 3.1.7 无条件转移 116 3.2 重复执行语句块 117 3.2.1 循环的概念 117 3.2.2 for循环的变体 119 3.2.3 while循环 126 3.2.4 do-while循环 128 3.2.5 嵌套的循环 129 3.3 c++/cli编程 132 3.4 小结 137 3.5 练习 138 3.6 本章主要内容 138 第4章 数组、字符串和指针 139 4.1 处理多个相同类型的数据值 139 4.1.1 数组 140 4.1.2 声明数组 140 4.1.3 初始化数组 143 4.1.4 字符数组和字符串处理 144 4.1.5 多维数组 147 4.2 间接数据访问 150 4.2.1 指针的概念 150 4.2.2 声明指针 150 4.2.3 使用指针 152 4.2.4 初始化指针 152 4.2.5 sizeof操作符 158 4.2.6 常量指针和指向常量的指针 159 4.2.7 指针和数组 161 4.3 动态内存分配 168 4.3.1 堆的别名—— 空闲存储器 168 4.3.2 new和delete操作符 168 4.3.3 为数组动态分配内存 169 4.3.4 多维数组的动态分配 171 4.4 使用引用 172 4.4.1 引用的概念 172 4.4.2 声明并初始化lvalue引用 172 4.4.3 声明并初始化rvalue引用 173 4.5 字符串的本地c++库函数 174 4.5.1 查找以空字符结尾的字符串的长度 174 4.5.2 连接以空字符结尾的字符串 174 4.5.3 复制以空字符结尾的字符串 176 4.5.4 比较以空字符结尾的字符串 177 4.5.5 搜索以空字符结尾的字符串 177 4.6 c++/cli编程 179 4.6.1 跟踪句柄 180 4.6.2 clr数组 181 4.6.3 字符串 195 4.6.4 跟踪引用 203 4.6.5 内部指针 204 4.7 小结 206 4.8 练习 206 4.9 本章主要内容 207 第5章 程序结构(1) 209 5.1 理解函数 209 5.1.1 需要函数的原因 210 5.1.2 函数的结构 210 5.1.3 使用函数 213 5.2 给函数传递实参 216 5.2.1 按值传递机制 216 5.2.2 给函数传递指针实参 217 5.2.3 给函数传递数组 219 5.2.4 给函数传递引用实参 222 5.2.5 使用const修饰符 224 5.2.6 rvalue引用形参 225 5.2.7 main()函数的实参 227 5.2.8 接受数量不定的函数实参 229 5.3 从函数返回值 231 5.3.1 返回指针 231 5.3.2 返回引用 233 5.3.3 函数中的静态变量 236 5.4 递归函数调用 238 5.5 c++/cli编程 240 5.5.1 接受数量可变实参的函数 241 5.5.2 main( )的实参 242 5.6 小结 243 5.7 练习 243 5.8 本章主要内容 244 第6章 程序结构(2) 245 6.1 函数指针 245 6.1.1 声明函数指针 246 6.1.2 函数指针作为实参 249 6.1.3 函数指针的数组 250 6.2 初始化函数形参 250 6.3 异常 252 6.3.1 抛出异常 253 6.3.2 捕获异常 254 6.3.3 mfc中的异常处理 255 6.4 处理内存分配错误 256 6.5 函数重载 257 6.5.1 函数重载的概念 258 6.5.2 引用类型和重载选择 260 6.5.3 何时重载函数 260 6.6 函数模板 261 6.7 使用decltype操作符 263 6.8 使用函数的示例 265 6.8.1 实现计算器 265 6.8.2 从字符串中删除空格 268 6.8.3 计算表达式的值 268 6.8.4 获得项值 270 6.8.5 分析数 271 6.8.6 整合程序 274 6.8.7 扩展程序 275 6.8.8 提取子字符串 277 6.8.9 运行修改过的程序 279 6.9 c++/cli编程 279 6.9.1 理解泛型函数 280 6.9.2 clr版本的计算器程序 285 6.10 小结 290 6.11 练习 291 6.12 本章主要内容 292 第7章 自定义数据类型 293 7.1 c++中的结构 293 7.1.1 结构的概念 294 7.1.2 定义结构 294 7.1.3 初始化结构 294 7.1.4 访问结构的成员 295 7.1.5 伴随结构的智能感知帮助 298 7.1.6 rect结构 299 7.1.7 使用指针处理结构 300 7.2 数据类型、对象、类和实例 301 7.2.1 类的起源 303 7.2.2 类的操作 303 7.2.3 术语 303 7.3 理解类 304 7.3.1 定义类 304 7.3.2 声明类的对象 305 7.3.3 访问类的数据成员 305 7.3.4 类的成员函数 307 7.3.5 成员函数定义的位置 309 7.3.6 内联函数 309 7.4 类构造函数 310 7.4.1 构造函数的概念 311 7.4.2 默认的构造函数 312 7.4.3 在类定义中指定默认形参值 314 7.4.4 在构造函数中使用初始化列表 316 7.4.5 声明显式的构造函数 317 7.5 类的私有成员 318 7.5.1 访问私有类成员 320 7.5.2 类的友元函数 321 7.5.3 默认复制构造函数 323 7.6 this指针 325 7.7 类的const对象 327 7.7.1 类的const成员函数 327 7.7.2 类外部的成员函数定义 328 7.8 类对象的数组 329 7.9 类的静态成员 331 7.9.1 类的静态数据成员 331 7.9.2 类的静态函数成员 334 7.10 类对象的指针和引用 334 7.10.1 类对象的指针 334 7.10.2 类对象的引用 337 7.11 c++/cli编程 338 7.11.1 定义值类类型 339 7.11.2 定义引用类类型 344 7.11.3 定义引用类类型的复制构造函数 346 7.11.4 类属性 346 7.11.5 initonly字段 358 7.11.6 静态构造函数 360 7.12 小结 360 7.13 练习 360 7.14 本章主要内容 361 第8章 深入理解类 363 8.1 类析构函数 363 8.1.1 析构函数的概念 363 8.1.2 默认的析构函数 364 8.1.3 析构函数与动态内存分配 366 8.2 实现复制构造函数 369 8.3 在变量之间共享内存 370 8.3.1 定义联合 371 8.3.2 匿名联合 372 8.3.3 类和结构中的联合 372 8.4 运算符重载 373 …… 第9章 类继承和虚函数 第10章 标准模板库 第11章 调试技术 第12章 windows编程的概念 第13章 多核编程 第14章 使用mfc编写windows程序 第15章 处理菜单和工具栏 第16章 在窗口中绘图 第17章 创建文档和改进视图 第18章 使用对话框和控件 第19章 存储和打印文档 第20章 编写自己的dll
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值