静态数据成员
用static修饰类中的数据成员,被称为静态数据成员。他并不依赖于对象的实例化,而依赖于类。所以静态数据成员不在构造函数中初始化,它单独进行初始化;就算对象没有实例化,他也存在。而普通数据成员依赖于对象的实例化,若对象没有实例化,它就不存在。
假设有一个Tank类
class Tank
{
public:
Tank(char code);
~Tank();
void fire();
static int getCount();//静态成员函数
private:
static int s_iCount;//静态数据成员,该函数用来记录坦克个数
char m_cCode;//坦克的名称
};
若对象还没有实例化,可以用 类名::静态数据成员名称 来访问
Tank::s_iCount;
普通数据成员和静态数据成员的区别:
实例化tank之后,s_iCount的值会变化,但是他在内存中的个数仍然为1个,而m_strCode会有很多个(根据实例化了几个对象)
因此,静态数据成员只有一份
静态成员函数
理论:静态成员函数不能调用非静态成员函数和非静态数据成员,但是可以调用静态数据成员
原理:
还是前面的代码
static int getCount()
{
m_strCode = '01''//错误
}
因为静态成员函数同样也不依赖于对象,所以在这个静态成员函数的参数中无this指针,那么在调用非静态数据成员m_strCode的时候,编译器无法知道调用哪一个对象的数据成员,则会编译出错。
而静态成员函数可以调用静态数据成员是因为静态数据成员在内存中就一个,不需要区分。
注:static成员函数不可以用const修饰,因为用const修饰的成员函数,实质上是const修饰的成员函数参数中隐藏的this指针,而static成员函数无this指针。
总结:
- 静态数据成员必须单独初始化
- 静态成员函数不能调用非静态成员函数和非静态数据成员
- 静态数据成员只有一份,且不依赖对象而存在
代码示例
#include<iostream>
using namespace std;
class Tank
{
public:
Tank(char code);
~Tank();
void fire();
static int getCount();//静态成员函数
private:
static int s_iCount;//静态数据成员
char m_cCode;
};
int Tank::s_iCount = 10;//对静态数据成员初始化,在构造函数的外面进行
Tank::Tank(char code)
{
m_cCode = code;
s_iCount++;
cout<<"Tank"<<endl;
}
Tank::~Tank()
{
s_iCount--;
cout<<"~Tank"<<endl;
}
void Tank::fire()
{
cout<<"Tank--fire"<<endl;
}
int Tank::getCount()//在类外定义的时候,不需要在前面加static
{
return s_iCount;
}
int main()
{
cout<<Tank::getCount()<<endl;
Tank *p = new Tank('A');
cout<<Tank::getCount()<<endl;
Tank *q = new Tank('B');
cout<<q->getCount()<<endl;
delete p;
p = NULL;
delete q;
q = NULL;
cout<<Tank::getCount()<<endl;
return 0;
}
运行结果: