静态成员:在说明前面加了static关键字的成员。
基本概念
普通成员变量每个对象有各自的一份,而静态成员变量一共就一份,为所有对象所共享。
sezeof运算符不会计算静态成员变量:
class CMyclass{
int n;
static int s;
};
//则sizeof(CMyclass)等于4
普通成员函数必须具体作用于某个对象,而静态成员函数并不具体作用于某个对象,因此静态成员不需要通过对象就能访问。
静态成员变量本质上是全局变量,哪怕一个对象都不存在,类的静态成员变量也存在。静态成员函数本质上是全局函数。
如何访问静态成员
1)类名::成员名
CRectangle::PrintTotal();
2)对象名.成员名
CRectangle r; r.PrintTotal();
3)指针->成员名
CRectangle *p=&r; p->PrintTotal();
4)引用.成员名
CRectangle & ref=r; int n=ref.nTotalNumber;
静态成员示例
考虑一个需要随时知道矩形总数和总面积的图形处理程序,这两个变量只与矩形类有关,与具体的矩形对象无关,因此设置为静态变量。
class CRectangle{
private:
int w,h;
static int nTotalArea;
static int nTotalNumber;
public:
CRectangle(int w_,int h_);
~CRectangle();
static void PrintTotal();
};
CRectangle::CRectangle(int w_,int h_)
{
w=w_;
h=h_;
nTotalNumber++;
nTotalArea+=w*h;
}
CRectangle::~CRectangle()
{
nTotalNumber--;
nTotalArea-=w*h;
}
void CRectangle::PrintTotal()
{
cout<<nTotalNumber<<","<<nTotalArea<<endl;
}
int CRectangle::nTotalNumber=0;
int CRectangle::nTotalArea=0;
//静态成员变量必须在类定义的括号外面进行声明,可以初始化也可以不初始化,但是必须声明
int main()
{
CRectangle r1(3,3),r2(2,2);
cout<<CRectangle::nTotalNumber;//错误,私有变量
CRectangle::PrintTotal();
r1.PrintTotal();
return 0;
}
输出结果:
2,13
2,13
tips:
1.静态成员变量必须在类定义的括号外面进行声明,可以初始化也可以不初始化,但是必须声明。否则,编译能够通过但是链接不能通过。
2.在静态成员函数中,不能访问非静态成员变量,也不能调用非静态成员函数。
void CRectangle::PrintTotal()
{
cout<<w<<","<<nTotalNumber<<","<<nTotalArea<<endl;//错误
}
CRectangle::PrintTotal();//解释不通w到底属于哪个对象
3.上述CRectangle类的写法有缺陷,在使用CRectangle类时,有时会调用复制构造函数生成临时的CRectangle对象,临时对象在消亡时会调用析构函数,减少nTotalNumber和nTotalArea的值,但是这些临时对象在生成时却没有增加nTotalNumber和nTotalArea的值。
解决办法:为CRectangle类写一个复制构造函数
CRectangle::CRectangle(CRectangle &r)
{
w=r.w; h=r.h;
nTotalNumber++;
nTotalArea+=w*h;
}