C++对C的扩展
1.最简单的C++程序
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
2.类和对象初体验
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
3.类里面必须要有成员函数
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
说明:在使用类定义对象的时候,编译器会根据类的成员变量的初始值初始化对象的成员变量。就算更改了某个成员变量的值,并不会更改与之关联的成员变量的值。
如果要程序执行相关语句,必须通过调用成员函数的方式得以实现。
2.与C语言的关系
1.C语言是在实践的过程中逐步完善起来的
- 没有深思熟虑的设计过程
- 使用时存在很多“灰色地带”
- 残留过多低级语言的特征
- 直接利用指针进行内存操作
2.C语言的目标是高效
最终程序执行效率的高效
3.当面向过程方法论暴露越来越多的缺陷的时候,业界开始考虑在工程项目中引入面向对象的设计方法,而第一个需要解决的问题就是:高效的面向对象语言,并且能够兼容已经存在的代码。
C语言 + 面向对象方法论===》Objective C /C++
4.C语言和C++并不是对立的竞争关系
- C++是C语言的加强,是一种更好的C语言
- C++是以C语言为基础的,并且完全兼容C语言的特性
5.学习C++并不会影响原有的C语言知识,相反会加深对C的认知,学习C++可以接触到更多的软件设计方法,并带来更多的机会。
- C++是一种更强大的C,通过学习C++能够掌握更多的软件设计方法
- C++是Java/C#/D等现代开发语言的基础,学习C++后能够快速掌握这些语言
- C++是各大知名软件企业挑选人才的标准之一
3.发展历史
1.面向过程的结构化程序设计方法
- 设计思路
- 自顶向下、逐步求精。采用模块分解与功能抽象,自顶向下、分而治之。
- 程序结构:
- 按功能划分为若干个基本模块,形成一个树状结构。
- 各模块间的关系尽可能简单,功能上相对独立;每一模块内部均是由顺序、选择和循环三种基本结构组成。
- 其模块化实现的具体方法是使用子程序。
- 优点:
有效地将一个较复杂的程序系统设计任务分解成许多易于控制和处理的子任务,便于开发和维护。 - 缺点:可重用性差、数据安全性差、难以开发大型软件和图形界面的应用软件
- 把数据和处理数据的过程分离为相互独立的实体。
- 当数据结构改变时,所有相关的处理过程都要进行相应的修改。
- 每一种相对于老问题的新方法都要带来额外的开销。
- 图形用户界面的应用程序,很难用过程来描述和实现,开发和维护也都很困难。
2.面向对象的方法
- 将数据及对数据的操作方法封装在一起,作为一个相互依存、不可分离的整体——对象。
- 对同类型对象抽象出其共性,形成类。
- 类通过一个简单的外部接口,与外界发生关系。
- 对象与对象之间通过消息进行通信。
3.面向对象的基本概念
- 对象
- 一般意义上的对象:
- 是现实世界中一个实际存在的事物。
- 可以是有形的(比如一辆汽车),也可以是无形的(比如一项计划)。
- 是构成世界的一个独立单位,具有
- 静态特征:可以用某种数据来描述
- 动态特征:对象所表现的行为或具有的功能
- 面向对象方法中的对象:
- 是系统中用来描述客观事物的一个实体,它是用来构成系统的一个基本单位。对象由一组属性和一组行为构成。
- 属性:用来描述对象静态特征的数据项。
- 行为:用来描述对象动态特征的操作序列。
- 一般意义上的对象:
- 类
- 分类——人类通常的思维方法
- 分类所依据的原则——抽象
- 忽略事物的非本质特征,只注意那些与当前目标有关的本质特征,从而找出事物的共性,把具有共同性质的事物划分为一类,得出一个抽象的概念。
- 例如,石头、树木、汽车、房屋等都是人们在长期的生产和生活实践中抽象出的概念。
- 面向对象方法中的”类”
- 具有相同属性和服务的一组对象的集合
- 为属于该类的全部对象提供了抽象的描述,包括属性和行为两个主要部分。
- 类与对象的关系:
犹如模具与铸件之间的关系,一个属于某类的对象称为该类的一个实例。
- 封装
也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
- 把对象的属性和服务结合成一个独立的系统单元。
- 尽可能隐蔽对象的内部细节。对外形成一个边界(或者说一道屏障),只保留有限的对外接口使之与外部发生联系。
- 继承对于软件复用有着重要意义,是面向对象技术能够提高软件开发效率的重要原因之一。
- 定义:特殊类的对象拥有其一般类的全部属性与服务,称作特殊类对一般类的继承。
- 例如:将轮船作为一个一般类,客轮便是一个特殊类。
-
多态
多态是指在一般类中定义的属性或行为,被特殊类继承之后,可以具有不同的数据类型或表现出不同的行为。这使得同一个属性或行为在一般类及其各个特殊类中具有不同的语义。 -
面向对象的软件工程
面向对象的软件工程是面向对象方法在软件工程领域的全面应用。它包括:- 面向对象的分析(OOA)
- 面向对象的设计(OOD)
- 面向对象的编程(OOP)
- 面向对象的测试(OOT)
- 面向对象的软件维护(OOSM)
总结:
面向过程程序设计:数据结构 + 算法
主要解决科学计算问题,用户需求简单而固定
特点:
分析解决问题所需要的步骤
利用函数实现各个步骤
依次调用函数解决问题
问题:
软件可重用性差
软件可维护性差
构建的软件无法满足用户需求
面向对象程序设计:由现实世界建立软件模型
将现实世界中的事物直接映射到程序中,可直接满足用户需求
特点:
直接分析用户需求中涉及的各个实体
在代码中描述现实世界中的实体
在代码中关联各个实体协同工作解决问题
优势:
构建的软件能够适应用户需求的不断变化
直接利用面向过程方法的优势而避开其劣势
4.对C语言的加强
4.1命名空间
1.基本常识
所谓namespace,是指标识符的各种可见范围。C++标准程序库中的所有标识符都被定义于一个名为std的namespace中。
-
iostream和iostream.h格式不一样,前者没有后缀,实际上,在你的编译器include文件夹里面可以看到,二者是两个文件,打开文件就会发现,里面的代码是不一样的。后缀为.h的头文件c++标准已经明确提出不支持了,早些的实现将标准库功能定义在全局空间里,声明在带.h后缀的头文件里,c++标准为了和C区别开,也为了正确使用命名空间,规定头文件不使用后缀.h。 因此:
-
当使用
<iostream.h>
时,相当于在c中调用库函数,使用的是全局命名空间,也就是早期的c++实现; -
当使用
<iostream>
的时候,该头文件没有定义全局命名空间,必须使用namespace std;这样才能正确使用cout。
-
-
由于namespace的概念,使用C++标准程序库的任何标识符时,可以有三种选择:
- 直接指定标识符。例如std::ostream而不是ostream。完整语句如下:
std::cout << std::hex << 3.4 << std::endl;
- 使用using关键字。 using std::cout; using std::endl; using std::cin; 以上程序可以写成
cout << std::hex << 3.4 << endl;
- 最方便的就是使用using namespace std; 例如:
using namespace std;
这样命名空间std内定义的所有标识符都有效(曝光)。就好像它们被声明为全局变量一样。那么以上语句可以如下写:cout <<hex << 3.4 << endl;
- 直接指定标识符。例如std::ostream而不是ostream。完整语句如下:
-
因为标准库非常的庞大,所以程序员在选择的类的名称或函数名 时就很有可能和标准库中的某个名字相同。所以为了避免这种情况所造成的名字冲突,就把标准库中的一切都被放在名字空间std中。但这又会带来了一个新问 题。无数原有的C++代码都依赖于使用了多年的伪标准库中的功能,他们都是在全局空间下的。所以就有了
<iostream.h>
和<iostream>
等等这样的头文件,一个是为了兼容以前的C++代码,一个是为了支持新的标准。命名空间std封装的是标准程序库的名称,标准程序库为了和以前的头文件区别,一般不加”.h” -
C中的命名空间
- 在C语言中只有一个全局作用域
- C语言中所有的全局标识符共享同一个作用域
- 标识符之间可能发生冲突
- C++中提出了命名空间的概念
- 命名空间将全局作用域分成不同的部分
- 不同命名空间中的标识符可以同名而不会发生冲突
- 命名空间可以相互嵌套
- 全局作用域也叫默认命名空间
2.命名空间定义及使用语法
-
C++命名空间的定义:
namespace name { … } -
C++命名空间的使用:
- 使用整个命名空间:using namespace name;
- 使用命名空间中的变量:using name::variable;
- 使用默认命名空间中的变量:::variable
- 默认情况下可以直接使用默 认命名空间中的所有标识符
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
3.结论:
- 当使用的时候,该头文件没有定义全局命名空间,必须使用namespace std;这样才能正确使用cout。若不引入using namespace std ,需要这样做。std::cout。
- c++标准为了和C区别开,也为了正确使用命名空间,规定头文件不使用后缀.h。
- C++命名空间的定义: namespace name { … }
- using namespace NameSpaceA;
- namespce定义可嵌套。
4.2实用性增强
C语言中的变量都必须在作用域开始的位置定义!!C++中更强调语言的“实用性”,所有的变量都可以在需要使用时再定义。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
4.3register增强
register关键字 请求编译器让变量a直接放在寄存器里面,速度快.在c语言中 register修饰的变量不能取地址,但是在c++里面做了增强。
1.register关键字的变化
register关键字请求“编译器”将局部变量存储于寄存器中
- C语言中无法取得register变量地址
- 在C++中依然支持register关键字
- C++编译器有自己的优化方式,不使用register也可能做优化
- C++中可以取得register变量的地址
2.C++编译器发现程序中需要取register变量的地址时,register对变量的声明变得无效。
3.早期C语言编译器不会对代码进行优化,因此register变量是一个很好的补充。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
4.4变量检测增强
- 在C语言中,重复定义多个同名的全局变量是合法的
- 在C++中,不允许定义多个同名的全局变量
- C语言中多个同名的全局变量最终会被链接到全局数据区的同一个地址空间上
- 1
- 2
- 3
- C++直接拒绝这种二义性的做法。
4.5struct增强
-
C语言的struct定义了一组变量的集合,C编译器并不认为这是一种新的类型,声明结构体变量的时候需要带上struct关键字或者事先使用typedef关键字声明。
-
C++中的struct是一个新类型的定义声明,声明结构体变量的时候可不带struct关键字。
-
struct和class具有相同的功能,但是也有区别。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
4.6类型增强
C++中所有的变量和函数都必须有类型
C语言中的默认类型在C++中是不合法的
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 函数f的返回值是什么类型,参数又是什么类型?
- 函数g可以接受多少个参数?
上述程序再C++编译器编译不通过,因为对变量和函数类型进行了增强。
在C语言中
int f( );表示返回值为int,接受任意参数的函数
int f(void);表示返回值为int的无参函数
在C++中
int f( );和int f(void)具有相同的意义,都表示返回值为int的无参函数
C++更加强调类型,任意的程序元素都必须显示指明类型
4.7新增bool类型
- C++在C语言的基本类型系统之上增加了bool
- C++中的bool可取的值只有true和false
- 理论上bool只占用一个字节,
-
如果多个bool变量定义在一起,可能会各占一个bit,这取决于编译器的实现
-
true代表真值,编译器内部用1来表示
-
false代表非真值,编译器内部用0来表示
-
bool类型只有true(非0)和false(0)两个值
- C++编译器会在赋值时将非0值转换为true,0值转换为false
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
4.8三目运算符增强
- C语言返回变量的值 C++语言是返回变量本身
- C语言中的三目运算符返回的是变量值,不能作为左值使用
- C++中的三目运算符可直接返回变量本身,因此可以出现在程序的任何地方
注意:三目运算符可能返回的值中如果有一个是常量值,则不能作为左值使用(a < b ? 1 : b )= 30;
- C语言如何支持类似C++的特性呢?
当左值的条件:要有内存空间;C++编译器帮助程序员取了一个地址而已。
思考:如何让C中的三目运算法当左值呢?
答:*(a < b ? &a :& b )= 30;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
5.const关键字
5.1基础知识
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
-
初级理解:const是定义常量==》const意味着只读
-
含义:
- 第一个第二个意思一样 代表一个常整形数
- 第三个 c是一个指向常整形数的指针(所指向的内存数据不能被修改,但是本身可以修改)
- 第四个 d 常指针(指针变量不能被修改,但是它所指向内存空间可以被修改)
- 第五个 e一个指向常整形的常指针(指针和它所指向的内存空间,均不能被修改)
-
Const好处
- 合理的利用const,
- 1指针做函数参数,可以有效的提高代码可读性,减少bug;
- 2清楚的分清参数的输入和输出特性
-
int setTeacher_err( const Teacher *p)
Const修饰形参的时候,不能利用形参修改指针所向的内存空间
5.2C语言的冒牌货
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
解释:
C++编译器对const常量的处理
当碰见常量声明时,在符号表中放入常量
问题:那有如何解释取地址
编译过程中若发现使用常量则直接以符号表中的值替换
编译过程中若发现对const修饰的变量使用了extern或者&操作符,则给对应的常量分配存储空间(兼容C)
注意:
C++编译器虽然可能为const常量分配空间,但不会使用其存储空间中的值。
5.3与#define的关系
C++中的const修饰的,是一个真正的常量,而不是C中变量(只读)。const修饰的常量在编译期间,就已经确定下来了。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- C++中的const常量类似于宏定义
const int c = 5; ≈ #define c 5 - C++中的const常量与宏定义不同
- const常量是由编译器处理的,提供类型检查和作用域检查
- 宏定义由预处理器处理,单纯的文本替换
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
5.4结论
- C语言中的const变量
C语言中const变量是只读变量,有自己的存储空间
-
C++中的const常量
-可能分配存储空间,也可能不分配存储空间- 当const常量为全局,并且需要在其它文件中使用,会分配存储空间
- 当使用&操作符,取const常量的地址时,会分配存储空间
-
当const int &a = 10;
-
const修饰引用时,也会分配存储空间
6.新引入的“引用”概念
1.背景
- 变量名回顾
变量名实质上是一段连续存储空间的别名,是一个标号(门牌号) -
程序中通过变量来申请并命名内存空间
通过变量的名字可以使用存储空间 -
问题1:对一段连续的内存空间只能取一个别名吗?
2.引用概念
a) 在C++中新增加了引用的概念
b) 引用可以看作一个已定义变量的别名
c) 引用的语法:Type& name = var;必须有初始值;
d) 引用做函数参数?(引用作为函数参数声明时不进行初始化,即形参不需初始化)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
3.作函数参数
普通引用在声明时必须用其它的变量进行初始化,
引用作为函数参数声明时不进行初始化
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
4.意义
1)引用作为其它变量的别名而存在,因此在一些场合可以代替指针
2)引用相对于指针来说具有更好的可读性和实用性
5.思考
- 思考1:C++编译器背后做了什么工作?
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
单独定义的引用时,必须初始化;说明很像一个常量
- 思考2:普通引用有自己的空间吗?
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
64位系统
说明引用占的内存空间大小和指针一样
6.本质
1)引用在C++中的内部实现是一个常指针
Type& name == Type* const name
2)C++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同。
3)从使用的角度,引用会让人误会其只是一个别名,没有自己的存储空间。这是C++为了实用性而做出的细节隐藏
4)间接赋值成立的三个条件
- 定义两个变量 (一个实参一个形参)
- 建立关联 实参取地址传给形参
- *p形参去间接的修改实参的值
结论:1)引用在实现上,只不过是把:间接赋值成立的三个条件的后两步和二为一
//当实参传给形参引用的时候,只不过是c++编译器帮我们程序员手工取了一个实参地址,传给了形参引用(指针常量)
2)当我们使用引用语法的时,我们不去关心编译器的引用是怎么做的;
当我们分析奇怪的语法现象的时,我们才去考虑c++编译器是怎么做的。
7.函数的返回值是引用
-
综述
C++引用使用时的难点:- 当函数返回值为引用时
- 若返回栈变量
- 不能成为其它引用的初始值
- 不能作为左值使用
- 若返回静态变量或全局变量
- 可以成为其他引用的初始值
- 即可作为右值使用,也可作为左值使用
- C++链式编程中,经常用到引用,运算符重载专题
- 当函数返回值为引用时
-
返回值是基础类型
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 返回值是static变量
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 返回值是形参
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 返回值非基础类型
如果返回引用不是基础类型,是一个类,那么情况非常复杂。。涉及到copy构造函数和=操作重载,抛砖。。。。
8.指针引用
就是数据类型是指针类型的引用,示例代码如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
9.常引用
-
如果用变量初始化常引用,使得引用变量(引用代表的内存空间)具有只读属性,只能通过指针的方式修改变量或者通过修改原变量的方式修改
-
如果使用字面值初始化常引用,使得编译器为字面值分配内存空间而不是放到符号表,引用名就是该段空间的别名
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
总结:
1)const int & e
相当于const int * const e
2)普通引用 相当于int *const e
3)当使用常量(字面量)对const引用进行初始化时,C++编译器会为常量值分配空间,并将引用名作为这段空间的别名
4)使用字面量对const引用初始化后,将生成一个只读变量(引用变量是只读的)
7.对C函数的扩展
7.1 关于内联函数的几点说明:
- 必须
inline int myfunc(int a, int b)
和函数体的实现,写在一块 - C++编译器直接将函数体插入在函数调用的地方,内联函数在最终生成的代码中是没有定义的
- 内联函数没有普通函数调用时的额外开销(压栈,跳转,返回)
- C++编译器不一定准许函数的内联请求!
- 内联函数是一种特殊的函数,具有普通函数的特征(参数检查,返回类型等)
- 内联函数由编译器处理,直接将编译后的函数体插入调用的地方,宏代码片段由预处理器处理,进行简单的文本替换,没有任何编译过程
- 现代C++编译器能够进行编译优化,因此一些函数即使没有inline声明,也可能被编译器内联编译
另外,一些现代C++编译器提供了扩展语法,能够对函数进行强制内联
如:g++中的__attribute__((always_inline))
属性 -
C++中内联编译的限制:
- 不能存在任何形式的循环语句
- 不能存在过多的条件判断语句
- 函数体不能过于庞大
- 不能对函数进行取址操作
- 函数内联声明必须在调用语句之前
-
编译器对于内联函数的限制并不是绝对的,内联函数相对于普通函数的优势只是省去了函数调用时压栈,跳转和返回的开销。因此,当函数体的执行开销远大于压栈,跳转和返回所用的开销时,那么内联将无意义。
-
和宏代码片段想比还是具有优势的
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
7.2 函数参数
1.默认参数
-
C++中可以在函数声明时为参数提供一个默认值,
当函数调用时没有指定这个参数的值,编译器会自动用默认值代替 -
函数默认参数的规则
只有参数列表后面部分的参数才可以提供默认参数值,一旦在一个函数调用中开始使用默认参数值,那么这个参数后的所有参数都必须使用默认参数值
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
2.占位参数
函数占位参数
占位参数只有参数类型声明,而没有参数名声明
一般情况下,在函数体内部无法使用占位参数
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
3.两者关系
可以将占位参数与默认参数结合起来使用
意义
为以后程序的扩展留下线索
兼容C语言程序中可能出现的不规范写法
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
结论:如果默认参数和占位参数在一起,都能调用起来
7.3 函数重载
1.基本概念
-
函数重载概念
函数重载(Function Overload)
用同一个函数名定义不同的函数
当函数名和不同的参数搭配时函数的含义不同 -
函数重载的判断标准
函数重载至少满足下面的一个条件:
参数个数不同
参数类型不同
参数顺序不同 -
函数返回值不是函数重载的判断标准
2.函数重载的调用准则
- 将所有同名函数作为候选者
- 尝试寻找可行的候选函数
- 精确匹配实参
- 通过默认参数能够匹配实参
- 通过默认类型转换匹配实参
- 匹配失败
- 最终寻找到的可行候选函数不唯一,则出现二义性,编译失败。
- 无法匹配所有候选者,函数未定义,编译失败。
3.函数重载的注意事项
- 重载函数在本质上是相互独立的不同函数(静态链编)
- 重载函数的函数类型是不同的
- 函数返回值不能作为函数重载的依据
- 函数重载是由函数名和参数列表决定的。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
4.函数重载和函数默认参数混搭
容易出现二义性导致编译失败
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
5.函数重载和函数指针
重载函数和函数指针所表示的函数类型要匹配才能将重载函数给函数指针赋值。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
附录1:C++语言对C语言扩充和增强的几点具体体现
附录2:C语言register关键字—最快的关键字