大家好
欢迎来到实验5
本章的目标是掌握多文件结构
数据的共享与保护
理解标识符的作用域
和对象的可见性
const关键字的应用
友元等语法现象
本部分的实验内容
是通过练习
来帮助大家进一步地理解
和掌握标识符的作用域
可见性和生存期
静态数据成员的使用
以及多文件结构
在C++程序中的应用
大家在学习这一章的时候
可能会感觉和其他章节比
这章的内容显得特别的庞杂
语法规定非常的多
不过只要按照程序结构
和数据共享这两条主线
思路就会清晰一些
标识符的作用域 可见性
和对象的生存期问题
是研究和理解
程序模块之间数据共享
数据保护的基础
在接下来的例题一中
我们就将通过一个简单的小例子
来观察和体验一下
静态成员是类的对象之间
共享数据和代码的手段
而多文件结构
则是大型程序开发中的
分工合作的一种方式
在接下来的例题中
我们就来使用一下静态成员
并体会一下多文件结构的使用
首先我们来看例题一
运行下面准备好的程序
注意观察变量x y
在不同地方输出的时候的值
分别是多少
我们来看一下这个例子程序
在这里我们声明了一个函数
叫fn1
还声明了一个int类型的变量x
和int类型的变量y
那么因为x和y呢
并没有被任何的花括号所包含
所以它是具有全局作用域的
或者是具有
文件作用域的全局变量
接着我们进入main函数
在main函数中
我们首先输出了x y
这个时候x y的值
当然对应的应该是
对 对应的是全局变量x等于1
y等于2
然后呢
我们就进入下一个步骤
在这里
我们声明了
main函数的内部的局部变量x
值为10 y为20
接着进行打印输出
那这个时候的x呢
对 因为有了局部变量x
它就会把同名的全局变量x
给屏蔽隐藏掉
所以在这里输出的x的值是10
同样地
在这里输出的y的值
就应该是局部变量20
然后我们进入了fn1这个函数
我们看一下
它到底发生了些什么
在fn1这个函数内部
全局变量x y仍然起作用
但是这个时候呢
我们声明了一个局部变量y
它的值是200
注意在这里的局部变量y
和全局变量y是同名的
因此全局变量
会被局部变量y隐藏
所以在这里输出的x
是全局变量x
它的值是1
而这里的y呢
是fn1中的局部变量y
它的值是200
然后我们又回到main函数中
再次打印输出x的值和y的值
当然在这个时候的x和y值
就如我们前面一样
在这里一样
它是main函数中的局部变量
x 10 y 20
这样整个例子程序就结束了
接下来我们在return这里
设置一个断点
来运行一下
看看结果是否如我们预期
我们可以看到确实如此
在刚进main函数的时候
x的值和y的值
是全局变量x y的值分别是1和2
然后在main函数中
因为声明了main函数
内部的局部变量x y
所以在这个地方
它就会把全局变量屏蔽掉
这里输出的值是
main函数的局部变量
x的值是10 y的值是20
在fn1中由于局部变量y
把全局变量y屏蔽掉了
所以这里输出的x值
是全局变量x1
局部变量y 200
然后再回到main函数中
这时候的x y值
和我们在之前输出的
main函数的x y值是一样的
它们是在main函数中的局部变量
x等于10 局部变量y等于20
那这个例子很简单
到这里就结束了
有兴趣的同学
可以利用我们前面反复用到的
f10和f11来单步地
跟踪和调试一下这个例子程序
来进一步地体会和理解
局部变量 全局变量
以及局部变量把全局变量
屏蔽的情形
接下来我们来看例题二
例题二要求我们
实现一个客户机类CLIENT类
要求声明一个数据成员
叫ServerName
它是一个字符型的静态数据成员
用来保存服务器的名称
声明一个整型的静态数据成员
ClientNum
用来记录已经定义的客户数量
因为这两个成员
都是静态数据成员
所以我们需要声明静态函数
来操作它们
在这里要求定义一个静态函数
名字叫ChangeSeverName
用来改变服务器的名称
我们在这里呢
不仅仅是要求
实现这样一个客户机类
还要求大家练习使用一下
多文件结构
那我们要求在头文件client.h中
声明类client
在文件client.cpp中实现这个类
在文件test.cpp中来测试这个类
请大家在测试类的时候
观察相应的成员变量
取值的变化情况
接下来我们就来看一下
我们的代码
首先我们来观察一下
client.h这个文件
按照要求呢
它是一个头文件
在里面只需要给出类client声明
我们这个类很简单
按照要求它有两个数据成员
分别是SeverName和ClientNum
前面用static关键字来修饰
表示这两个成员
都是静态数据成员
也就是整个类中
所有对象共享的成员
那如果要操作这两个成员呢
我们就需要用静态函数
来操作它们
所以接下来呢
Public的接口是两个静态函数
一个是用来改变服务器名称的
ChangeServerName
另外一个呢
是用来获得当前服务器个数的
getClientNum
我们的头文件就到此为止
需要大家注意的是
因为我们的头文件
这个client.h
会很多次的未来
被包含在其他的文件中
所以为了避免重复包含的问题呢
我们在这里
要采用多文件结构中
经常使用的编译预处理指令
来避免重复包含
这个用了ifndef define
和endif
接下来我们再来看一下
client这个类的实现
我们在这个类的实现中呢
首先包含了这个类的定义
client.h
那么这个类呢
因为只有两个成员函数
所以执行的这个代码很简单
就是两个函数体
第一个函数体呢
我们对服务器的名称进行了改变
同时把服务器的个数自增1
那么在第二个函数里呢
我们直接把服务器的个数
进行返回
这里需要注意的是什么呢
需要注意的是
因为它是一个
static类型的静态成员函数
访问的是静态数据成员
所以我们在引用
静态数据成员的时候
需要注意前面加上类名的限定符
来进行修饰
那最后呢
我们在testcpp里
对刚才声明的client类
和定义的client类进行一下测试
因为静态数据成员呢
是不属于任何类的对象的
所以它需要在main函数之外
进行单独的初始化
那我们在这里
把ClientNum
也就是服气器的个数初始化为0
而把ServerName服务器的名字
初始为字符a
在main函数中的测试倒是很简单
我们首先构造了一个
client类的对象
叫c1
设置一下它的名字
然后返回一下
当前有多少个client对象啊
当然这个时候只有一个对象
所以我们预期
这里应该会输出一个1
接着我们又去声明了一个
client类的对象c2
设置了一下它的名字
那么接下来我们为了
请求获取一下当前多少个服务器了
当然这个时候应该输出是2
大家可以去跟踪一下
我们按下f11来进行跟踪
这个时候光标停留在
main函数的开始位置
我们在这个监视器中
设置了两个需要观测的量
是clint类的两个静态数据成员
ServerName和ClientNum
那我们执行到这里的时候
我们可以用f11跟踪一下
它确实就进入到了
这个静态函数成员内部
并且我们这个地方的局部变量
name的值
被实参的字符a进行了初始化
那么经过这个函数体的两个操作
ServerName和ClientNum
这两个静态成员
它们的值都会被更新了
这个时候SeverName被更新为
ASCII为97对应的字符
小写的a
ClientNume被更新为整数1
然后我们就返回到main函数内部
接下来
情形是类似的
我们直接把光标设置在这里
然后继续执行
我们可以看到
这里的ServerName
和ClientNum
在经过对象c2的操作之后呢
名字分别变成了b
然后服务器的数量变成了2
我们再来看一下
这个命令行窗口
这里也依次输出了1和2
和我们预期的还是完全一样
那我们的例题二就到这里
大家感兴趣呢
可以一步一步地继续
再跟踪下去
本章的语法规定比较多
有的同学觉得难以理解
还有的同学觉得逐一理解
并不难
但是记不住 还容易混淆
究其根本原因
都是没有透彻地
理解这些语法的现象
我建议大家用反证的方法
来帮助理解和加深印象
比如语法规定
在作用域之外
就不可以访问这个对象
那么您可以编写一个程序
在标识符的作用域之外
去访问一下这个标识符
看看会发生什么样的现象
还可以尝试用普通的成员函数
去处理一下常对象
看看会有什么现象
经过这样的验证
很多疑问就会解开了
学习后续的章节也是这样
遇到难以理解的问题
不妨去亲自动手写个程序
来实验一下
很多问题就迎刃而解了
实验5就到这里
谢谢大家
C++语言程序设计的基础篇
到这里就结束了
感谢大家的关注和学习
在4月27日
我们的C++语言程序进阶篇
将会上线
与大家见面
大家可以在学堂x搜索
C++语言程序设计
来加入进阶篇继续学习
你也可以推荐身边有基础的朋友
来加入进阶篇的学习