·静态成员:在说明前面加了static关键字的成员
class CRectangle{
private:
int w, h;
static int nTotalArea;//静态成员变量
static int nTotalNumber;
public:
CRectangle(int w_, int h_);
~CRectangle();
static void PrintTotal();//静态成员函数
};
·普通成员变量每个对象有各自的一份,而静态成员变量一共就一份,为所有对象共享。
sizeof运算符不会计算静态成员变量
class CMyclss{
int n;
static int s;
};
则sizeof(CMyclss) = 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::nTotalArea = 0;
int CRectangle::nTotalNumber = 0;
//必须在定义类的文件中对静态成员变量进行一次说明或初始化,否则编译能通过,链接不能通过
int main(){
CRectangle r1(3, 3), r2(2, 2);
cout << CRectangle::nTotalNumber;//Wrong,私有
CRectangle::PrintTotal();
r1.PrintTotal();
return 0;
}
输出结果:
2,13
2,13
·在静态成员函数中,不能访问非静态成员变量,也不能调用非静态成员函数
void CRectangle::PrintTotal(){
cout << w << "," << nTotalNumber << "," << nTotalArea << endl; //Wrong
}
CRectangle::PrintTotal();//解释不通,w到底是属于哪个对象的?
非静态成员函数中是有可能访问到一个非静态的成员变量,静态成员函数调用了费静态成员函数,则......
此CRectangle类写法,有何缺陷?
·在使用CRectangle类时,有时会调用复制构造函数生成临时的隐藏的CRectangle对象
调用一个以CRectangle类对象作为参数的函数时
调用一个以CRectangle类对象作为返回值的函数时
·临时对象在消亡时会调用析构函数,减少nTotalNumber和nTotalArea的值,可是这些临时对象在生成时却没有增加nTotalNumber和nTotalArea的值
解决办法:为CRectangle类写一个复制构造函数
CRectangle::CRectangle(CRectangle &r){
w = r.w; h = r.h;
nTotalNumber++;
nTotalArea += w * h;
}