c ++ - variables membres statiques et fonctions membres statiques

Préface

Les variables membres statiques C ++ sont déclarées avec le mot clé static. Ce sont des données membres de la classe entière . Leur stockage n'occupe pas l'espace d'un objet spécifique et elles sont stockées dans la zone de stockage statique .
Les fonctions membres statiques C ++ sont déclarées avec le mot clé static. Elles sont utilisées pour traiter les variables membres statiques. Elles peuvent être appelées par nom de classe ou par nom d' objet .

Le but de l' utilisation de variables membres statiques : les variables membres statiques sont des données membres de la classe entière , et l'utilisation de variables membres statiques permet d' obtenir plusieurs objets partageant des données .

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;
}

Résultat courant:
$ ./a.out
count = 0
1 2
count = 1
1 2
count = 2
0 0
count = 3
0 0
count = 4

Insérez la description de l'image ici
Comme le montre la figure, l'objet a occupe 8 octets (l'espace des membres x et y, count n'y est pas), et l'objet a est un objet local, stocké à la position 0x7fffffffdde0 sur la pile.
Insérez la description de l'image ici
Le décompte est stocké dans 0x555555756134 dans la zone de stockage statique , pas dans l'objet. Count appartient à la classe entière, pas à un objet spécifique.
La même chose est vraie pour les fonctions membres statiques, qui appartiennent à la classe entière, pas à un certain objet, donc les fonctions membres statiques peuvent être appelées avec le nom de la classe, tel que Point :: showcount ().

La variable membre statique doit être initialisée en dehors de la déclaration de classe, la forme spécifique est:

 type class::name = value;

Comme cet exemple: int Point :: count = 0;
les variables membres statiques ne peuvent pas ajouter de statique lorsqu'elles sont initialisées, mais doivent avoir un type de données.

La mémoire des variables membres statiques n'est allouée ni lorsque la classe est déclarée, ni lorsque l'objet est créé, mais lorsqu'il est initialisé (en dehors de la classe) . Les variables membres statiques qui ne sont pas initialisées en dehors de la classe ne peuvent pas être utilisées car aucun espace n'est alloué.

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;
}

Utilisez GDB pour afficher le stockage des variables membres statiques:
Insérez la description de l'image ici
vous pouvez voir que lorsque compte dans b devient 2, compter dans a devient également 2, c'est-à-dire que le compte dans a et b sont partagés. En regardant les adresses de a.count et b.count, vous pouvez constater qu'il s'agit de la même adresse, c'est-à-dire du même espace de stockage. Et cet espace de stockage est une zone de stockage globale (zone de stockage statique), pas dans la zone de stockage de pile de l'objet a et de l'objet b.
Dans cet exemple, count est public, modifié en protected et private, et erreur de compilation.

protected:
    static int count;

Insérez la description de l'image ici

private:
    static int count;

Insérez la description de l'image ici
Comme indiqué ci-dessus, c'est-à-dire si vous souhaitez accéder aux variables membres statiques via des objets, les variables membres statiques ne peuvent être que des attributs publics. C'est la même chose que lorsqu'un objet accède à des variables membres ordinaires. En dehors de la classe, les objets peuvent uniquement accéder aux variables membres publiques, mais pas aux variables membres protégées et privées.

Test 3:

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

Insérez la description de l'image ici
En d'autres termes, dans une fonction membre statique, vous ne pouvez pas accéder aux variables membres ordinaires. La raison est qu'il n'y a pas ce pointeur, et je ne sais pas où la variable membre ordinaire x est placée.
Analyse des raisons:
lorsque le compilateur compile une fonction membre ordinaire, il ajoutera implicitement un paramètre formel this, et attribuera l'adresse de l'objet actuel à celui-ci, de sorte que les fonctions membres ordinaires ne peuvent être appelées via l'objet qu'après la création de l' objet, car il L'adresse de l'objet actuel est requise. En d'autres termes, il existe un pointeur this d'un objet, et sans objet, les fonctions membres ordinaires ne peuvent pas être appelées. Étant donné que la classe n'a pas le pointeur this, vous ne pouvez pas utiliser le nom de classe pour appeler des fonctions membres ordinaires, vous pouvez uniquement utiliser l' objet réel pour appeler des fonctions membres ordinaires .

La fonction membre statique peut être appelée directement via la classe, le compilateur n'y ajoutera pas le paramètre formel, il n'a pas besoin de l'adresse de l'objet actuel, donc peu importe si l'objet est créé ou non, vous pouvez appeler la fonction membre statique. Parce que les fonctions membres statiques veulent accéder aux variables membres statiques (stockées dans la zone de stockage globale, rien à voir avec ce pointeur).
Étant donné que la fonction membre statique ne possède pas ce pointeur, elle ne sait pas sur quel objet elle pointe et ne peut pas accéder aux variables membres de l'objet. Par conséquent, la fonction membre statique ne peut pas accéder aux variables membres ordinaires, mais uniquement aux variables membres statiques .

Pour résumer:

  1. Il peut y avoir une ou plusieurs variables membres statiques dans une classe, et tous les objets partagent ces variables membres statiques et peuvent y faire référence. Notez qu'il s'agit d'un partage, d'un partage, d'un partage , c'est-à-dire qu'il n'occupera que le même espace de stockage statique .
  2. Les variables membres statiques sont les mêmes que les variables statiques ordinaires. La mémoire est allouée dans la zone de données globales de la partition mémoire et est libérée à la fin du programme. Cela signifie que les variables membres statiques n'allouent pas de mémoire avec la création de l'objet, ni ne libèrent de mémoire avec la destruction de l'objet. Les variables membres ordinaires allouent de la mémoire lorsque l'objet est créé et libèrent la mémoire lorsque l'objet est détruit. La raison fondamentale est que l'espace de stockage des variables membres statiques et des objets est différent et qu'ils sont alloués à des moments différents .
  3. Les variables membres statiques doivent être initialisées et ne peuvent être effectuées qu'en dehors de la classe. Par exemple:
    int Point :: count = 0;
    La valeur initiale peut être attribuée ou non lors de l'initialisation. Si aucune valeur n'est affectée, elle sera initialisée à 0 par défaut .
    Les variables de la zone de données globales ont une valeur initiale par défaut de 0, tandis que la valeur par défaut de la variable ** zone de données dynamiques (zone de tas, zone de pile) ** est incertaine et est généralement considérée comme une valeur de garbage.
  4. Les variables membres statiques sont accessibles via le nom de l' objet ou le nom de la classe , mais sous réserve des restrictions d'autorité d'accès des mots-clés privé, protégé et public.
    Lorsque la classe à l'extérieur lors de l'accès à la surface par nom d'objet, les propriétés des variables membres statiques doivent être publiques , pour différents objets, un accès mémoire est le même (essentiellement partager ).
  5. La fonction membre statique doit être statique lorsqu'elle est déclarée et statique ne peut pas être ajoutée lors de la définition . Les fonctions membres statiques ne peuvent accéder qu'aux variables membres statiques , pour accéder aux variables membres ordinaires, la compilation signalera une erreur.

Je suppose que tu aimes

Origine blog.csdn.net/u014470361/article/details/103225030
conseillé
Classement