静态数据成员是一种特殊的数据成员,它属于类不属于对象,但是这个类的所有对象使用它。
/***********************************
第五篇
***********************************/
引入:一般不同对象的数据成员各自有值,互不相干;但是有时候希望某个或者几个数据成员为所有对象所共有,从而实现数据共享。
解决方法一:使用全局变量,全局变量在程序中的任何位置都可以访问修改它的值,虽然可以但是安全性得不到保障。
解决方法二:使用类的静态数据成员。有了静态成员,各对象之间的数据有了沟通的渠道,实现数据共享,因此可以不适用全局变量;全局变量破坏了类的封装性原则,不符合面向对象的要求。
一、静态数据成员
静态数据成员特点:
静态的数据成员在内存中只占一份空间(而不是每个对象都分别为它保留一份空间);只要定义了静态数据成员,即使没有定义对象,也为它分配了存储空间。简言之,就是它属于类,而不属于对象。
我们知道,在一个函数中定义静态变量情况下,在函数结束时该变量并不释放,仍然保留其值。现在的静态数据成员与之类似,它不随着对象的建立分配空间,也不随对象的撤销而释放。静态数据成员时再程序编译时分配空间,在程序结束时释放空间。
1)静态数据成员的声明以关键字static开头,其他与一般数据成员声明一样。如:
staticint s_Total;//静态数据成员
注意:
3)静态数据成员初始化:只能在类外初始化。
int Critter::s_Total = 0;(无论其是private,还是public,都这么初始化)
4)静态数据成员的访问
可以通过类名来引用,也可以通过对象名来引用。【前者更可显示出它“属于类”的特性,推荐这种方法】
例: cout<<Critter::s_Total<<endl;//通过类名引用
cout<<crit.s_Total<<endl;//通过对象名引用
静态成员函数既可以是public,也可以是private的。前者可以在类外直接引用,后者只能通过公用的成员函数来访问它。
二、静态成员函数
同静态数据成员一样,静态成员函数是类的一部分,而不是对象的一部分。
作用:静态数据成员时为了类的对象之间的沟通,而静态成员函数是为了处理静态数据成员。
特点:
1)为什么说静态成员函数不是对象的一部分,而是类的一部分呢?因为静态成员函数没有this指针。因此,在这种函数中不能对一个对象中的非静态成员进行默认访问(即在引用数据成员时不指定对象名)。(这也是非静态成员函数和静态成员函数的本质区别。)
2)然而在静态成员函数可以直接引用静态数据成员,因为静态数据成员同样也是属于类的。
静态成员函数的定义:只要在普通成员函数的定义前添加static关键字就是定义静态成员函数了。例:
staticintGetTotal()
{
return s_Toatal;
}
静态成员函数的访问:public型的静态成员函数既可以通过类名调用,也可以通过对象名调用。
【前者更能代表它是静态的,是类的一部分;故而推荐这种方法】
例:
cout<<Critter::GetTotal()<<endl;//通过类名调用
cout<<crit.GetToatal()<<endl;//通过对象名调用
下面例子来自《C++游戏编程入门教程》来说明static的例子:
//Static Critter //介绍静态数据成员和静态成员函数
#include<iostream> usingnamespace std; classCritter { public: staticint s_Total;//静态数据成员 //现有的Critter对象的总数 Critter(int hunger =0): m_Hunger(hunger) { cout <<"A critter has been born!"<< endl; ++s_Total; } staticintGetTotal()//static member function { return s_Total; } private: int m_Hunger; };
intCritter::s_Total =0;// 初始化静态数据成员 int main() { cout <<"The total number of critters is: "; cout <<Critter::s_Total <<"\n\n";Critter crit1, crit2, crit3; cout <<"\nThe total number of critters is: "; cout <<Critter::GetTotal()<<"\n"; return0; }