.
void main(){ cout<<\第一次输出:\ //引用文件作用域的对象globClock : globClock.showTime();//对象的成员函数具有类作用域 globClock.setTime(8,30,30); Clock myClock(globClock);//声明具有块作用域的对象 cout<<\第二次输出:\ myClock.showTime();//引用具有块作用域的对象 } 5.3 类的静态成员P153
静态成员是解决同一个类的不同对象之间的数据和函数共享问题的。 例,抽象出某公司全体雇员的共性,设计如下的雇员类: class Employee{//雇员类 private : int empNo ; int id ; string name ;//字符串对象 ... } 若需要统计雇员总数,这个数据存放在什么地方呢? 若以类外的变量来存储总数,不能实现数据的隐藏。 若在类中增加一个数据成员用以存放总数,必然在每一个对象中都存储一个副本,不仅冗余,且每个对象分别维护一个“总数”,势必造成数据的不一致性。
比较理想的方案是类的所有对象共同拥有一个用于存放总数的数据成员。
5.3.1 静态数据成员P154
实例属性
“一个类的所有对象具有相同的属性”,是指属性的个数、名称、数据类型相同,各个对象的属性值则可各不相同。以类的非静态数据成员表示。
类属性
是描述类的所有对象的共同特征的一个数据项,对于任何对象实例,它的属性值是相同的。通过静态数据成员来实现“类属性”。
.
.
静态数据成员的访问
静态数据成员不属于任何一个对象,只能通过类名对它访问,用法是“类名::标识符”。
静态数据成员的说明和定义
在类的声明中仅仅对静态数据成员进行引用性说明,必须在文件作用域的某处用类名限定进行定义性说明,这时也可进行初始化。
在UML中,静态数据成员下方添加下划线。
例5-4 具有静态数据成员的Point类。
引入静态数据成员的Point类。
图5-2 包含静态数据成员的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
.
void main() { Point a(4,5);//定义对象a,其构造函数会使count增1 cout<<\ a.showCount();//输出对象个数 Point b(a); //定义对象b,其拷贝构造函数会使count增1 cout<<\ b.showCount(); } 在对类的静态私有数据成员初始化的同时,还可引用类的其他私有成员。例,若一个类T存在类型T的静态私有对象,则可引用该类的私有构造函数将其初始化。
5.3.2 静态函数成员P156
静态成员函数是使用static关键字声明的函数成员。
静态成员函数属于整个类,由同一个类的所有对象共同维护,并共享。 对于公有的静态成员函数,可通过类名或对象名来调用。
静态成员函数可直接访问该类的静态数据和函数成员,而访问非静态数据成员,必须通过参数传递方式得到对象名,然后通过对象名来访问。 class A{ public: static void f(A a); private: int x; }; void A::f(A a){ cout<
图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&) <
.
可不依赖于任何对象,直接访问静态数据。
5.4 类的友元P158
友元提供了不同类或对象的成员函数之间、类的成员函数与一般函数之间进行数据共享的机制。
在一个类中,可用关键字friend将其他函数或类声明为友元。 若友元是一般函数或类的成员函数,称友元函数;
若友元是一个类,称友元类,友元类的所有成员函数都自动成为友元函数。
5.4.1 友元函数P160
友元函数是在类中用关键字friend修饰的非成员函数。 友元函数不是本类的成员函数,但是在它的函数体中可通过对象名访问类的私有和保护成员。
在UML中,友元函数前添加<
例5-6 使用友元函数计算两点间的距离。
图5-4 包含友元函数成员的Point类的UML图
Point – x : int – y : int +Point(xx : int=0, yy : int=0) +getX() : int +getY() : int <