技术交流QQ群:1027579432,欢迎你的加入!

1.Cpp中类的静态成员

  • 可以使用static关键字来把类成员定义为静态的。当我们声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本。静态成员在类的所有对象中是共享的。如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零。我们不能把静态成员的初始化放置在类的定义中,但是可以在类的外部通过使用范围解析运算符::来重新声明静态变量从而对它进行初始化,如下面的实例所示:
    #include "iostream"
    
        using namespace std;
    
        class Box{
            public:
                static int count;  // 声明一个静态成员变量!
                Box(double l, double w, double h): length(l), width(w), height(h){
                    cout << "这是Box类对象的构造函数....\n";
                    count++; // 每创建一个Box类的对象时,count增加1
                }
                double getVolume(){
                    return length * width * height;
                }
            private:
                double length;
                double width;
                double height;
        };
        // 静态成员变量要在类外初始化!
        int Box::count = 0;
    
    
        int main(){
            Box box1(3.2, 1.4, 5.5);
            Box box2(6.6, 4.2, 8.7);
            cout << "Box类总共的对象数是: " << Box::count << endl;
            return 0;
        }

2.静态成员函数

  • 如果把函数成员声明为静态的,就可以把函数与类的任何特定对象独立开来。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符::就可以访问。静态成员函数只能访问静态成员数据、其他静态成员函数和类外部的其他函数
  • 静态成员函数有一个类范围,它们不能访问类的this指针。可以使用静态成员函数来判断类的某些对象是否已被创建。静态成员函数与普通成员函数的区别:
    • 静态成员函数没有this指针,只能访问静态成员(包括静态成员变量和静态成员函数);
    • 普通成员函数有this指针,可以访问类中的任意成员,而静态成员函数没有this指针
  • 静态成员函数实例如下:
    #include "iostream"
    
        using namespace std;
    
        class Box{
            public:
                static int count;  // 声明一个静态成员变量!
                Box(double l, double w, double h): length(l), width(w), height(h){
                    cout << "这是Box类对象的构造函数....\n";
                    count++; // 每创建一个Box类的对象时,count增加1
                }
                double getVolume(){
                    return length * width * height;
                }
                // 静态成员函数定义!!!
                static int getCount(){
                    return count;
                }
            private:
                double length;
                double width;
                double height;
        };
        // 静态成员变量要在类外初始化!
        int Box::count = 0;
    
    
        int main(){
            // 在创建对象前输出对象的总数
            cout << "未创建对象前的对象数是: " << Box::getCount() << endl;
            Box box1(3.2, 1.4, 5.5);
            Box box2(6.6, 4.2, 8.7);
            cout << "Box类总共的对象数是: " << Box::getCount() << endl;
            return 0;
        }
  • 类的静态成员细节知识
    • 静态成员变量在类中仅仅是声明,没有定义。所以要在类的外面定义,实际上是给静态成员变量分配内存。如果不加定义就会报错,初始化是赋一个初始值,而定义是分配内存
      #include "iostream"
      
          using namespace std;
      
          class Box{
              public:
                  static int count;  // 声明一个静态成员变量!
                  Box(double l, double w, double h): length(l), width(w), height(h){
                      cout << "这是Box类对象的构造函数....\n";
                      count++; // 每创建一个Box类的对象时,count增加1
                  }
                  double getVolume(){
                      return length * width * height;
                  }
              private:
                  double length;
                  double width;
                  double height;
          };
          // 初始化类Box的静态成员 ,其实是定义并初始化的过程
          int Box::count = 0;
          // 也可这样 定义却不初始化
          int Box::count;
          int main(){
              Box box1(3.2, 1.4, 5.5);
              Box box2(6.6, 4.2, 8.7);
              cout << "Box类总共的对象数是: " << Box::count << endl;
              return 0;
          }
    • 可以使用静态成员变量清楚了解构造与析构函数的调用情况
      // 可以使用静态成员变量清楚了解构造与析构函数的调用情况
          class Cpoint{
              public:
                  static int value;
                  static int num;
                  Cpoint(int x, int y): xp(x), yp(y){
                      value++;
                      cout << "调用构造: " << value << endl;
                      cout << this->xp << " " << this->yp << endl;
                  }
                  ~Cpoint(){
                      num++;
                      cout << "调用析构: " << num << endl;
                  }
              private:
                  int xp;
                  int yp;
          };
      
          // 静态成员变量初始化
          int Cpoint::num = 0;
          int Cpoint::value = 0;
      
      
          class CRect{
              public:
                  CRect(int x1, int x2): mpt1(x1, x2), mpt2(x1, x2){
                      cout << "调用构造\n";
                  }
                  ~CRect(){
                      cout << "调用析构\n";
                  }
              private:
                  Cpoint mpt1, mpt2;
          };
          CRect p(10, 20);
          cout << "hello world!\n";
      • 上述程序的分析:构造p时,先调用CRect的构造函数,在使用初始化列表初始化字段mpt1和mpt2时,又调用Cpoint的构造函数两次;析构p时,先调用CRect的析构函数并输出,然后析构成员mpt1和mpt2,且顺序是先调用mpt2的析构函数,再调用mpt1的析构函数。发现析构的过程和构造过程完全相反
        class Cpoint{
                public:
                    static int value;
                    static int num;
                    Cpoint(int x, int y): xp(x), yp(y){
                        value++;
                        cout << "调用构造: " << value << endl;
                        cout << this->xp << " " << this->yp << endl;
                    }
                    ~Cpoint(){
                        num++;
                        cout << "调用析构: " << num << endl;
                        cout << this->xp << " " << this->yp << endl;
                    }
                private:
                    int xp;
                    int yp;
            };
        
            // 静态成员变量初始化
            int Cpoint::num = 0;
            int Cpoint::value = 0;
        
        
            class CRect{
                public:
                    CRect(int x1, int x2): mpt1(x1, x1), mpt2(x2, x2){
                        cout << "调用构造\n";
                    }
                    ~CRect(){
                        cout << "调用析构\n";
                    }
                private:
                    Cpoint mpt1, mpt2;
            };
            CRect p(10, 20);
            cout << "hello world!\n";