静态成员变量和静态成员函数

2019-05-04  本文已影响0人  波洛的汽车电子世界

注:以下大部分内容来源于 coursera 课程《C++程序设计》

  1. 静态成员:在定义前加了关键字static 的成员
  2. 包括静态成员变量和静态成员函数
  3. 与普通成员的差别:普通成员变量每个对象有各自的一份,静态成员变量一共就一份,为所有对象共享。sizeof()不会计算静态成员变量。
  4. 普通成员函数必须具体作用于某个对象,而静态成员函数并不具体作用于某个对象。
  5. 静态成员不需要通过对象就能访问。
  6. 静态成员变量本质上是全局变量,不依靠于对象。静态成员函数是全局函数。

如何访问静态成员?

  1. 通过类名::成员名
    Crectangle:PrintTotal();
  2. 对象名.成员名
    Crectangle r;
    r.PrintTotal();
    注意:虽然这里是r.PrintTotal,但是PrintTotal并不是作用在r上面的,这只是一种形式。
  3. 指针->成员名
    Crectangle *p = &r;
    p->PrintTotal();
  4. 引用->成员名
    Crectangle &re = r;
    int f = re.nTotalNumber;

例子:

考虑一个需要随时知道矩形总数和总面积的图形处理程序,可以用全局变量来记录总数和总面积。
思路:将nTotalNumber++写在构造函数里面,只要有矩形对象的生成,就会自动调用构造函数。
将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(2,2), r2(3,3);
//cout << CRectangle::nTotalNumber; // Wrong , 私有
CRectangle::PrintTotal();
r1.PrintTotal();
return 0;

}

void CRectangle::PrintTotal()
{
cout<<w<<nTotalNumber<<","<<nTotalArea<<endl;
//w是非静态成员变量,不能访问,此条语句错误。
}

*缺陷:忽略了复制构造函数。
在使用CRectangle类时,有时会调用复制构造函数生成临时的隐藏的CRectangle对象。

//构造函数
CRectangle::CRectangle(int w_, int h_)
{
w=w_;
h=h_;
nTotalNumber++;
nTotalArea += w*h;
}
//析构函数
CRectangle::~CRectangle(){
nTotalNumber--;
nTotalArea -= w*h;
}

这个构造函数里面,对TotalNumber和TotalArea进行增加,这是没问题的。但是并不是所有的CRectangle的对象都会用这个构造函数来初始化。 有可能有一些CRectangle的对象,它是用复制构造函数来初始化的,
例子1: 如果调用了一个以CRectangle对象作为形参的函数的时候,这个形参对象就是由复制构造函数初始化的。
例子2:调用了一个以CRectangle对象作为返回值的函数的时候,那这个返回值对象它也是用复制构造函数初始化的。
这样的对象它们生成的时候并没有走构造函数,也就是并没有增加TotalNumber和TotalArea, 但它们在消亡的时候,却一定要走析构函数,就会减掉TotalNumber和TotalArea, 所以这个时候问题就产生了,就会发生总数和这个总面积比实际的情况要少的情况。
例子3: 临时对象在消亡的时候也会调用析构函数。
如果一个函数的返回值是一个对象的话,那这个函数的返回值就是一个临时对象。

上一篇下一篇

猜你喜欢

热点阅读