3-C++程序的结构1.2
对象的生存周期
可以分为静态生存周期和动态生存周期
1、静态生存周期
如果对象的生存期与程序的运行期相同,我们称它具有静态生存期。在文件作用域中声明的对象都具有静态生存期的。如果要在函数的块中声明具有静态生存期的对象,则要使用关键字static。
2、动态生存期
除了上述两种情况,其余的对象都具有动态生存期。动态生存期对象诞生于声明点,结束于该标示符作用域结束处。
类的静态成员
在结构化的程序设计中程序模块的基本单位是函数,那么模块间对内存中数据的共享是通过函数与函数之间的数据共享来实现的,包括参数传递和全局变量。
静态成员是解决同一个类的不同对象之间数据和函数共享问题的。如,把某公司的全体雇员抽象如下,
class employee
{
private:
int EmpNo;
int ID;
char *name;
//...
}
这时,如果需要统计全体员工的总数,该怎么处理呢,如果直接加上一个变量到类里面,势必会造成每个对象都会包含此变量,而且容易造成不一致,比较理想的方案是类的所有对象共同拥有一个用于存放总数的数据成员,这就是需要借助静态数据成员。
1、静态数据成员
我们说“一个类的所有对象具有相同的属性”,是指属性的个数、名称、数据类型相同,各个对象的属性值则可以不相同,这样的属性在面向对象方法中称为“实例属性”。在c++程序中以类的非静态数据成员表示。
面向对象方法中还有“类属性”的概念。如果某个属性为整个类所共有,不属于任何一个具体对象,则采用static关键字来声明静态成员。静态成员在每一个类只有一个拷贝,由该类的所有对象共同维护和使用,从而实现了同一类的不同对象之间的数据共享。类属性是描述类的所有对象共同特征的一个数据项,对于任何对象实例,它的属性是相同的。
静态数据成员具有静态生存周期。它只能通过类名进行访问,一般的用法是“类名::标识符”。在类的定义中仅仅对静态数据成员进行声明,必须在文件作用域的某个地方使用类名限定对静态数据成员进行定义,这时也可以进行初始化。
2、静态函数成员
所谓静态成员函数就是使用static关键字声明的函数成员,同静态数据成员一样,静态成员函数页属于整个类,由同一个类的所有对象共同拥有,为这些对象所共享。
作为成员函数,它的访问属性可以受到类的严格控制,对于公有的静态成员函数,可以通过类名或对象名来调用,而一般的非静态成员函数只能通过对象名来调用。
静态成员函数可以直接访问类的静态数据和函数成员。而访问非静态数据成员必须通过参数传递方式得到对象名,然后通过对象名来访问。如,
class A
{
public:
static void f(A a);
private:
int x;
};
void A::f(A a)
{
cout<<x;//对x的引用时错误的
cout<<a.x;//正确
}
可以看到,通过静态函数成员访问非静态成员是相当麻烦的,一般情况下,它主要用来访问同一类中的静态数据成员,维护对象之间共享的数据。
#include<iostream>
using namespace std;
class Point //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<<"Object id="<<countP<<endl;}
private:
int X,Y;
static int countP;
};
Point::Point(Point &p)
{
X=p.X;
Y=p.Y;
countP++;
}
int Point::countP=0; //静态数据成员定义及初始化,初始化使用类名限定
int main()
{
Point A(4,5);
cout<<"Point A,"<<A.GetX()<<","<<A.GetY();
A.GetC();
Point B(A);
cout<<"Point B,"<<B.GetX()<<","<<B.GetY();
Point::GetC();
return 0;
}
使用静态数据成员时还应该注意:如果要通过非静态函数来访问静态数据成员,应该使用非内联函数,而且访问静态数据成员的函数,其函数体的定义应该与静态成员额初始化写在同一个文件中。