c++-static member variables and static member functions

Preface

C++ static member variables are declared with the static keyword. They are data members of the entire class . Their storage does not occupy the space of a specific object, and they are stored in the static storage area .
C++ static member functions are declared with the static keyword. They are used to process static member variables. They can be called by class name or object name .

The purpose of using static member variables : Static member variables are data members of the entire class , and using static member variables can achieve multiple objects sharing data .

Test 1:

#include <iostream>
using namespace std;

class Point{
public:
    Point(int xx,int yy):x(xx),y(yy){count++;}
    Point():Point(0,0){}
    Point(const Point &p);
    ~Point(){count--;}
    void show(){cout<<x<<" "<<y<<endl;}
    static void showcount();  //用static来声明静态成员函数
private:
    int x,y;
    static int count; //用static来声明静态成员变量
};

int Point::count = 0;   //静态成员变量的定义,定义时前面不可以再有static, 且它必须要在类外面来初始化,不能在类内部初始化。静态成员变量在初始化时分配内存。

void Point::showcount() {    //静态成员函数的定义,前面不可以再有static,可以在类内部定义,也可以在类外定义。此例为在类外面进行定义。
    cout<<"count="<<count<<endl;
}

Point::Point(const Point &p){  //复制构造函数
    x = p.x;
    y = p.y;
    count++;
}

Point fun(Point m){ 
    return m;
}

int main(){
    Point::showcount(); //用     类名::函数名      来调用静态成员函数
    Point a(1,2);
    a.show();
    a.showcount();//也可用    对象名.函数名   来调用静态成员函数
    Point b(a);
    b.show();
    b.showcount();
    Point c;
    c.show();
    c.showcount();
    Point d = fun(c);
    d.show();
    d.showcount();
    return 0;
}

Running result:
$ ./a.out
count=0
1 2
count=1
1 2
count=2
0 0
count=3
0 0
count=4

Insert picture description here
As shown in the figure, the object a occupies 8 bytes (the space of members x and y, count is not in it), and the object a is a local object, stored at the position of 0x7fffffffdde0 on the stack.
Insert picture description here
The count is stored in 0x555555756134 in the static storage area , not in the object. Count belongs to the entire class, not to a specific object.
The same is true for static member functions, which belong to the entire class, not to a certain object, so static member functions can be called with the class name, such as Point::showcount().

The static member variable must be initialized outside the class declaration, the specific form is:

 type class::name = value;

Such as this example: int Point::count = 0;
static member variables can not be added static during initialization, but must have a data type.

The memory of static member variables is neither allocated when the class is declared, nor when the object is created, but when it is initialized ( outside the class) . Static member variables that are not initialized outside the class cannot be used because no space is allocated.

Test 2:

#include <iostream>
#include <cmath>
using namespace std;

class Point{
public:
    Point(int xx,int yy):x(xx),y(yy){count++;}
    Point():Point(0,0){}
    Point(const Point &p);
    ~Point(){count--;}
    void show(){cout<<x<<" "<<y<<endl;}
    static void showcount();
public:
    static int count;   //此例为public属性
private:
    int x,y;
};

int Point::count = 0;
 
void Point::showcount() {
    cout<<"count="<<count<<endl;
}

Point::Point(const Point &p){
    x = p.x;
    y = p.y;
    count++;
}
int main(){
    Point::showcount();
    Point a(1,2);
    cout<<a.count<<endl;  //通过对象a来访问静态成员变量。若count不是public属性,不能用对象来访问,编译时就会报错
    Point::showcount();
    Point b(3,4);
    Point::showcount();

    return 0;
}

Use GDB to view the storage of static member variables:
Insert picture description here
you can see that when count in b becomes 2, count in a also becomes 2, that is, count in a and b are shared. Looking at the addresses of a.count and b.count, you can find that they are the same address, that is, the same storage space. And this storage space is a global storage area (static storage area), not in the stack storage area of ​​object a and object b.
In this example, count is public, modified to protected and private, and compile error.

protected:
    static int count;

Insert picture description here

private:
    static int count;

Insert picture description here
As shown above, that is to say, if you want to access static member variables through objects, static member variables can only be public attributes. This is the same as when an object accesses ordinary member variables. Outside the class, objects can only access public member variables, but not protected and private member variables.

Test 3:

void Point::showcount() {
    cout<<"count="<<count<<endl;
    cout<<x<<endl; //新增,尝试在静态成员函数中去访问普通的成员变量,编译报错。
}

Insert picture description here
In other words, in a static member function, you cannot access ordinary member variables. The reason is that there is no this pointer, and I don't know where the ordinary member variable x is placed.
Reason analysis:
When the compiler compiles an ordinary member function, it will implicitly add a formal parameter this, and assign the address of the current object to this, so ordinary member functions can only be called through the object after the object is created , because it The address of the current object is required. In other words, there is an object's this pointer, and without an object, ordinary member functions cannot be called. Since the class does not have the this pointer, you cannot use the class name to call ordinary member functions, but only use actual objects to call ordinary member functions .

The static member function can be called directly through the class, the compiler will not add the formal parameter this to it, it does not need the address of the current object, so no matter whether the object is created or not, you can call the static member function. Because static member functions want to access static member variables (stored in the global storage area, nothing to do with this pointer).
Since static member functions don't have this pointer, they don't know which object they point to, and cannot access the member variables of the object. Therefore, static member functions cannot access ordinary member variables, only static member variables .

to sum up:

  1. There can be one or more static member variables in a class. All objects share these static member variables and can reference it. Note that it is sharing, sharing, sharing , that is, it will only occupy the same static storage space .
  2. Static member variables are the same as ordinary static variables. Memory is allocated in the global data area of ​​the memory partition and is released at the end of the program. This means that static member variables do not allocate memory with the creation of the object, nor release memory with the destruction of the object. The ordinary member variables allocate memory when the object is created, and release the memory when the object is destroyed. The fundamental reason is that the storage space of static member variables and objects are different, and they are allocated at different times .
  3. Static member variables must be initialized, and can only be done outside the class. For example:
    int Point::count = 0;
    Initial value can be assigned or not assigned during initialization. If no value is assigned, it will be initialized to 0 by default .
    The variables in the global data area have a default initial value of 0, while the default value of the **dynamic data area (heap area, stack area)** variable is uncertain, and is generally regarded as a garbage value.
  4. Static member variables can be accessed through the object name or the class name , but subject to the access authority restrictions of the private, protected, and public keywords.
    When the class outside when surface access by object name, static member variables properties must be public , for different objects, a memory access is the same (essentially share ).
  5. Static member function should be static when declared, and static cannot be added when defining . Static member functions can only access static member variables , to access ordinary member variables, the compilation will report an error.

Guess you like

Origin blog.csdn.net/u014470361/article/details/103225030