静态成员数据是某一个类所具有的属性,而不是某一个对象的属性,所以它的存在并不依赖于对象。那么,如果一个类没有任何对象实例时,所有的普通成员函数都无法使用,我们该如何访问私有的静态成员数据呢?
既然成员数据可以属于某一个类而不属于某一个具体的对象,成员函数能否这样呢?答案是肯定的。在C++中,除了有静态成员数据,还有静态成员函数。静态成员函数也是属于某一个类而不属于某一个具体的对象的。静态成员函数的声明方法为:
static 返回值类型函数名(参数表);
不过,在声明静态成员函数时,却不能出现static。
下面我们就来看一下静态成员数据、静态成员函数在程序中如何使用:(程序16.1)
//node.h
class Node//声明一个链表结点类
{
public:
Node();//构造函数的声明
Node(Node &n);
Node(int i,char c='0');
Node(int i,char c,Node *p,Node *n);
~Node();//析构函数
int readi() const;
char readc() const;
Node * readp() const;
Node * readn() const;
bool set(int i);
bool set(char c);
bool setp(Node *p);
bool setn(Node *n);
static int allocation();//静态成员函数定义,返回已分配结点数
private:
int idata;//存储数据保密
char cdata;//存储数据保密
Node *prior;//前驱结点的存储位置保密
Node *next;//后继结点的存储位置保密
static int count;//静态成员数据,存储分配结点个数
};
//node.cpp,把类声明和定义拆分开了
#include "node.h"//如果没包含头文件连接时会出现错误
#include <iostream>
using namespace std;
int Node::count=0;//静态成员数据初始化
//未定义的函数与程序15.5相同
Node::Node()//构造函数的定义
{
cout <<"Node constructor is running..." <<endl;
count++;//分配结点数增加
idata=0;
cdata='0';
prior=NULL;
next=NULL;
}
Node::Node(int i,char c)//构造函数重载1
{
cout <<"Node constructor is running..." <<endl;
count++;//分配结点数增加
idata=i;
cdata=c;
prior=NULL;
next=NULL;
}
Node::Node(int i,char c,Node *p,Node *n)//构造函数重载2
{
cout <<"Node constructor is running..." <<endl;
count++;//分配结点数增加
idata=i;
cdata=c;
prior=p;
next=n;
}
Node::Node(Node &n)
{
count++;//分配结点数增加
idata=n.idata;
cdata=n.cdata;
prior=n.prior;
next=n.next;
}
Node::~Node()
{
count--;//分配结点数减少
cout <<"Node destructor is running..." <<endl;
}
int Node::allocation()//在定义静态成员函数时不能出现static
{
return count;//返回已分配结点数
}
//linklist.h同程序15.5
//main.cpp
#include "Linklist.h"
#include <iostream>
using namespace std;
int main()
{
int tempi;
char tempc;
cout <<"请输入一个整数和一个字符:" <<endl;
cin >>tempi >>tempc;
Linklist a(tempi,tempc);
a.Locate(tempi);
a.Insert(1,'C');
a.Insert(2,'B');
cout <<"After Insert" <<endl;
a.Show();
cout <<"Node Allocation:" <<Node::allocation() <<endl;//调用静态成员函数
Node b;
cout <<"An independent node created" <<endl;
cout <<"Node Allocation:" <<b.allocation() <<endl;//调用静态成员函数
return 0;
}
运行结果:
请输入一个整数和一个字符:
3 F
Node constructor is running...
Linklist constructor is running...
Node constructor is running...
Node constructor is running...
After Insert
3 F
2 B
1 C
Node Allocation:3
Node constructor is running...
An independent node created
Node Allocation:4
Node destructor is running...
Linklist destructor is running...
Node destructor is running...
Node destructor is running...
Node destructor is running...
可见,记录结点分配情况的功能已经实现。该程序中出现了两种调用静态成员函数的方法,一种是类名::静态成员函数名(参数表),另一种是对象名.静态成员函数名(参数表),这两种调用方法的效果是相同的。由于静态成员函数是属于类的,不是属于某一个具体对象,所以它分不清到底是访问哪个对象的非静态成员数据,故而不能访问非静态成员数据。
在第11章中,我们遇到过保留字static,其作用是使局部变量在函数运行结束后继续存在,成为静态变量。(或者说存储空间在编译时静态分配)而本章中static的含义是“每个类中只含有一个”,与第11章中的static毫不相关。所以说这里的static是名不符实的。