美文网首页
静态成员变量和静态成员函数

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

作者: 波洛的汽车电子世界 | 来源:发表于2019-05-04 17:16 被阅读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;
    
    }
    
    
    • 在C++里面,静态成员变量你必须拿到所有的函数外面来单独的给它声明一下。 必须在定义类的文件中对静态成员变量进行一次说明或初始化。否则编译能通过,链接不能通过。
    • 在静态成员函数中,不能访问非静态成员变量,也不能调用非静态成员函数。
    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: 临时对象在消亡的时候也会调用析构函数。
    如果一个函数的返回值是一个对象的话,那这个函数的返回值就是一个临时对象。

    • 解决办法: 为CRectangle类编写一个复制构造函数。
      我们自己写一个复制构造函数,在这个复制构造函数里面,除了我们做复制的工作以外,还要对这两个总数进行修改。

    相关文章

      网友评论

          本文标题:静态成员变量和静态成员函数

          本文链接:https://www.haomeiwen.com/subject/jymtoqtx.html