.\
实验05 数据的共享与保护(2学时)
(第5章 数据的共享与保护)
一、实验目的
(1) 观察程序运行中变量的作用域、生存期和可见性。
(2) 学习类的静态成员的使用。
(3) 学习多文件结构在C++程序中的使用。
二、实验任务
5_1 运行下面的程序,观察变量x、y的值。
//lab5_1.cpp
#include
using namespace std;
void fn1();
int x=1,y=2;
int main(){
cout<<"开始..."<
#include "client.h"
using namespace std;
client::client(){ ClientNum++; }//增加一个对象(客户)
client::~client(){ ClientNum--; }//减少一个对象(客户)
void client::ChangeServerName(char sn){ ServerName=sn; }//无static
void client::showServerName(){ cout<<"服务器名:"<
#include "client.h"
using namespace std;
void main(){
client::showServerName();//初始状态
client::showClientNum();//类名引用静态成员函数
client::ChangeServerName(B);
client a;//增加一个客户
a. showServerName();//对象名引用静态成员函数
a. showClientNum();
{
client b; //增加一个客户
b. showServerName();
b. showClientNum();
}//减少一个客户
client::showServerName();
client::showClientNum();
}
(4) 运行结果
附:第5章 数据的共享与保护
5.1 标识符的作用域与可见性P146
5.1.1 作用域
作用域是一个标识符在程序正文中有效的区域。
C++的作用域有:
函数原型作用域、块作用域(局部作用域)、类作用域、文件作用域。
1. 函数原型作用域
在函数原型声明时形式参数的作用范围。
例,
double Area(double radius);
其中标识符radius的作用(或称有效)范围在形参列表的左、右括号之间,称标识符radius的作用域是函数原型作用域。
由于在函数原型的形参表中起作用的只是形参类型,标识符并不起作用,可省略。
2. 局部作用域(块作用域)
例:
void fun(int a){
int b=a;
cin>>b;
if(b>0){
int c;
...
}
}
a的作用域
c的作用域
b的作用域
形参作用域:从形参列表中的声明处开始,到整个函数体结束处止。
b和c都具有块作用域,是不同的块作用域。
块是一对大括号括起来的一段程序。
此例,函数体是一个块,if语句后的分支体又是一个较小的块,二者是包含关系。
在块中声明的标识符,其作用域从声明处开始,一直到块结束的大括号为止。
具有块作用域的变量也称为局部变量。
3. 类作用域
类是一组有名成员的集合,类X的成员m具有类作用域,对m的访问方式如下:
(1) 若在X的成员函数中无同名的局部作用域标识符,则在该函数内可访问成员m。
(2) 通过表达式x.m或X::m。这正是程序中访问对象成员的最基本方法。
(3) 通过prt->m这样的表达式,其中prt为指向X类的一个对象的指针。
4. 命名空间作用域
命名空间
大型程序通常由不同模块构成,不同模块中的类和函数之间可能发生重名,将引发错误。
命名空间可以解决类名、函数等的命名冲突。
命名空间语法形式:
namespace 命名空间名{
命名空间内的各种声明(函数声明、类声明、……)
}
例
namespace SomeNs {
class SomeClass { ... };
}
特殊的命名空间
_ 全局命名空间:默认的命名空间
_ 匿名命名空间:对每个源文件是唯一的
命名空间作用域
一个命名空间确定了一个命名空间作用域
引用其它命名空间作用域中的标识符
_ 命名空间名::标识符名
_ 例:声明一个SomeClass型的对象
SomeNs::SomeClass obj1;
将其它命名空间作用域的标识符暴露于当前作用域
_ 对指定标识符
using 命名空间名::标识符名;
_ 对所有标识符
using namespace命名空间名;
例5-1中所声明的全局变量就具有文件作用域,它们在整个文件中都有效。
例5-1 作用域实例。
#include
using namespace std; //使得在当前文件中可直接引用std命名空间的标识符cout
int i;//全局变量,文件作用域
namespace Ns{
int j;//在Ns命名空间中的全局变量
}
void main()
{
i=5;//文件作用域的i赋初值
Ns::j=6;//为全局变量j赋值
{//子块1
using namespace Ns;//使得在当前块中可直接引用Ns命名空间的标识符
int i;//局部变量,块作用域
i=7;
cout<<"i="<
//using namespace std; //使得在当前文件中可直接引用std命名空间的标识符cout,endl
int i;//全局变量,文件作用域
namespace Ns{
int j;//在Ns命名空间中的全局变量
}
void main()
{
i=5;//文件作用域的i赋初值
Ns::j=6;//为全局变量j赋值
{//子块1
using namespace Ns;//使得在当前块中可直接引用Ns命名空间的标识符
int i;//局部变量,块作用域
i=7;
std::cout<<"i="<
using namespace std;
int i;//全局变量,文件作用域
namespace Ns{
int j;//在Ns命名空间中的全局变量
}
void main(){
i=5;//文件作用域的i赋初值
Ns::j=6;//为全局变量j赋值
{//子块1
using namespace Ns;
int i;//局部变量,块作用域
i=7;
cout<<"i="<
using namespace std;
int i=1;//i为全局变量,具有静态生存期
void other(void){
static int a=2;
static int b;//a, b为静态局部变量,具有全局寿命,局部可见,只第一次进入函数时被初始化
int c=10;//c为局部变量,具有动态生存期,每次进入函数时都初始化
a=a+2; i=i+32; c=c+5;
cout<<"---OTHER---\n";
cout<<"i:"<
using namespace std;
class Clock//时钟类定义
{
public:
Clock();
void setTime(int newH,int newM,int newS);//三个形参具有函数原型作用域
void showTime();
private:
int hour,minute,second;
};
//时钟类成员函数实现
Clock::Clock():hour(0),minute(0),second(0){ }//构造函数
void Clock::setTime(int newH,int newM,int newS)//3个形参均具有局部作用域
{ hour=newH; minute=newM; second=newS; }
void Clock::showTime(){ cout<
using namespace std;
class Point//Point类定义
{
public:
Point(int xx=0,int yy=0):x(xx),y(yy){ count++; }//所有对象共同维护count
Point(Point &p){ x=p.x; y=p.y; count++; }
~Point(){ count--; }
int getX(){ return x; }
int getY(){ return y; }
void showCount(){ cout<<" 对象count="<>。
例5-5 具有静态数据和函数成员的Point类。
图5-3 包含静态函数成员的Point类的UML图
Point
– x : int
– y : int
– count : int=0
+Point(xx : int=0, yy : int=0)
+getX() : int
+getY() : int
+Point(p : Point&)
<>+showCount() : void
#include
using namespace std;
class Point{
public:
Point(int xx=0,int yy=0):x(xx),y(yy){ count++; };
Point(Point &p){ x=p.x; y=p.y; count++; }
~Point(){ count--; }
int getX(){ return x; }
int getY(){ return y; }
static void showCount(){ cout<<" 对象count="<>。
例5-6 使用友元函数计算两点间的距离。
图5-4 包含友元函数成员的Point类的UML图
Point
– x : int
– y : int
+Point(xx : int=0, yy : int=0)
+getX() : int
+getY() : int
<>+dist(a : Point&, b : Point&) : foat
#include
#include
using namespace std;
class Point{//Point类定义
public:
Point(int xx=0,int yy=0):x(xx),y(yy){}
int getX(){ return x; }
int getY(){ return y; }
friend float dist(Point &p1,Point &p2);//友元函数声明
private:
int x,y;
};
float dist(Point &p1,Point &p2){//友元函数实现
double x=double(p1.x-p2.x);//通过对象访问私有数据成员
double y=double(p1.y-p2.y);
return static_cast(sqrt(x*x+y*y));
}
void main(){
Point myp1(1,1),myp2(4,5);
cout<<"距离是:";
cout<>构造型依赖来表征。
图5-5 类A和类B友元关系的UML图
B
+set(i : int) : void
+display() : void
A
– x : int
+display() : void
+getx() : int
<>
-a
#include
using namespace std;
class A{
public:
void display(){ cout<>。
例5-7 常成员函数举例。
图5-6 包含常成员函数的R类的UML图
R
– r1 : int
– r2 : int
+R(rr1 : int, rr2 : int)
+print() : void
<>+print() : void
#include
using namespace std;
class R{
public:
R(int rr1,int rr2):r1(rr1),r2(rr2){}
void print();
void print() const;//常成员函数
private:
int r1,r2;
};
void R::print(){ cout<
using namespace std;
class A{
public:
A(int i);
void print();
private:
const int a;//常数据成员
static const int b;//静态常数据成员
};
const int A::b=10;//静态常数据成员在类外说明和初始化
A::A(int i):a(i) { }//常数据成员只能通过初始化列表来获得初值
void A::print(){ cout<
#include
using namespace std;
class Point{//Point类定义
public:
Point(int xx=0,int yy=0):x(xx),y(yy){}
int getX(){ return x; }
int getY(){ return y; }
friend float dist(const Point &p1,const Point &p2);//友元函数声明
private:
int x,y;
};
float dist(const Point &p1, const Point &p2){//友元函数实现
double x=double(p1.x-p2.x);//通过对象访问私有数据成员
double y=double(p1.y-p2.y);
return static_cast(sqrt(x*x+y*y));
}
void main(){
const Point myp1(1,1),myp2(4,5);
cout<<"距离是:";
cout<
using namespace std;
class Point
{
public:
Point(int xx=0,int yy=0){X=xx; Y=yy; countP++; };
Point(Point &p);
~Point(){countP--;}
int GetX(){return X;}
int GetY(){return Y;}
static void GetC(){ cout<<"对象id="<
展开阅读全文
相关搜索