C++静态成员

来源:互联网 发布:淘宝手机端详情页 编辑:程序博客网 时间:2024/06/15 10:48
我们来看下静态成员吧。

一、静态成员的需要性及其概念。

大家清楚类是类型而不是数据对象,每个类的对象都是该数据成员的拷贝,然而我们往往需要让类的所有对象在类的范围内共享某个数据。当我们声明为static的类成员便能在类范围中共享,这就称为静态成员。静态成员是用于解决同一个类的不同对象之间的数据和函数的共享问题。

二,静态成员的使用。

成员有数据成员和函数成员之分,所以呢~!在类中静态成员也有静态数据成员和静态函数成员之分。

1,静态数据成员

在有些属性是类中所有对象共有的。我们先来看个例题:

我们可以抽象出学生的共性,设计如下的学生类:

class Student
{
private
    int Student NO;
    int ID
    chat*name
    //……
}

如果我们需要统计学生总数,那么这个数据存放在什么地方呢?若以类外的变量来存储总数,就不能实现数据的隐藏,这样既不安全又影响了重用性,若在类中增加一个数据成员用来存放总数,那必然在每一个对象中都存储一个副本,这样既冗雨余,而且每个对象分别维护一个“总数”,势必造成数据的不一致。那我们该怎么办呢?比较理想的发表国法是使用类的所有对象共同拥有一个用于存放总数的数据成员,这就是我们要讲的静态数据成员。

上面我们说过每个类的对象都是该数据成员的拷贝。也就是说,每个对象的通明数据成员可以分别存储不同的数据,这也是每个对象拥有自身特征的保证。而静态成员是类的数据成员的一种特例。每个类只有一个静态数据成员拷贝,他由该类的所有对象共同维护和使用,从而实现同一个类的不同对象之间的数据共享,同时,静态数据成员具有静态生存期。

这里我们插一点有关从C中继承过来的static的两种含义。

1)在固定的地址上分配,也就是说对象是在一个特殊的静态的数据区上创建的,而不是每次函数条用时在堆栈上产生的,这也就是静态存储的概念。

2)对一个特定的编译单位来说是本地的,这里的static控制名的可见性,所以这名字在这个单元或类之外是不可见的,这也描述连接的概念,他决定连接器将看到哪些名字。

现在,我们回到刚才,在静态数据成员的生命和使用时,应注意以下几点:
①静态数据成员声明时,应在前面加static关键字来说明。例如:static int n
②静态数据成员必须初始化,并且一定要在类外进行,其初始化的形式如下:<类型标识符><类名>::<静态数据成员>=<值> 例如:int point ::n=0;
③静态数据函数属于类,而不属于任何一个对象,所以,在类外只能通过类名对它进行引用,静态数据成员同一般数据成员一样要服从访问控制限制,当静态数据成员被声明为私有成员时,只能在类内直接引用,在类外无法引用,但当静态数据成员被声明为公有成员或保护成员时可以在类外通过类名对它进行引用,下面我们看个例题:
#include < iostream.h>
#include < string.h>
class Student
{
public:
  Student (char*pName ="no name")
  {
    cout <<"create one student /n";
    strcpy(name,pName);
    noOfStudent++;                     //静态成员,每创建一个对象学生人数+1
  }
~Student( )
{
  cout <<"destruct one studen /n";
  noOfStudent--;                       //每析构一个对象,学生人数减1
  cout <<noOfStudent << endl
}

static int numbler()                   //静态成员函数
{
  return noOfStudents;
}
prote cted
static int noOfStudents;             //若写成noOfStudent=0;则非法
  chat name[40];
};
int Student::noOfStudent =0;         //静态数据成员在类声明外分配空间和初始化

void fn()
{
  Student s1;
  Student s2;
  cout <<Studengt::numeber() <<endl; //调用静态函数用类名引导
}
void main()
{
  fn(0;
cout <<Student::number(0 <<endl;     //调用静态成员函数用类名引导
}

运行结果:
create one student
1
create one student
2 2
create one student
1
create one student
0 0

数据成员noOfStudents,既不是对象s1也不是对象s2的一部分。Student类随着对象的声明,每个对象都有一个name成员值,但无论对象有多少,甚至没有,静态成员noOfStudent也只有一个。所以Student对象都共享它,并且能够访问它。

在Student对象空间中,是没有静态数据成员noOfStudents的,他的空间不会随着对象的声明而分配,或随着对象的消失而回收。所以他的空间分配并不在Student的构造函数里完成,并且空间回收也不在类的析构函数里完成。

静态数据成员确实是程序一开始运行时就必须存在。因为函数在程序运行中被调用,所以静态数据成员不能在任何函数内分配空间和初始化。这样,他的空间分配有三个可能的地方,一是作为类的外部接口的头文件,那里有类声明;二是类定义的内部实现,那里有类成员函数定义;三是应用程序的main()函数前的全部数据声明和定义处。

静态数据成员要实际地分配空间,故不能在类声明定义(只能声明数据成员)。类声明只能声明一个类的“尺寸与规格”,并不是进行时间的内存分配,所以在类声明中写成定义“static int noOfStudent=0;”是错误的。他也不能在头文件中类生命的外部兵役,因为那会造成在多个使用该类的源文件中对其重复定义。

静态数据成员也不能在main(0函数之前的全局数据声明处顶因,因为那样会使每个重用该类的应用程序在包含了声明该类的头文件后,都不得在应用程序中再定义该类的静态成员。我们来大个比喻,我们去买个电饭煲,可商家告诉我们,盖子上的螺丝要自己拧上去,你说烦不烦?

例如:下面的代码重用Student类,但在应用程序中不得不再定义Student类的静态成员;
fle1.cpp                                 //student 类的内部实现部分
# include"student.h"                     //类的成员函数
file2.cpp                                 //类的成员函数

# include "student.h"
# include <iostream.h>

int Student :: noOfStudent=0;           //不便于重用

void fn()
{
  Student s1;
  Student s2;
  cout << Student::number() << endl;
}

void main()
{
  fn()
  cout << Student::number(0 << endl;
}

 
原创粉丝点击