Les champs statiques sont-ils hérités?

102

Lorsque les membres statiques sont hérités, sont-ils statiques pour toute la hiérarchie, ou simplement pour cette classe, c'est-à-dire:

class SomeClass
{
public:
    SomeClass(){total++;}
    static int total;
};

class SomeDerivedClass: public SomeClass
{
public:
    SomeDerivedClass(){total++;}
};

int main()
{
    SomeClass A;
    SomeClass B;
    SomeDerivedClass C;
    return 0;
}

le total serait-il de 3 dans les trois cas, ou serait-il de 2 pour SomeClasset de 1 pour SomeDerivedClass?

BartoszKP
la source

Réponses:

55

3 dans tous les cas, puisque le static int totalhérité de SomeDerivedClassest exactement celui de SomeClass, pas une variable distincte.

Edit: en fait 4 dans tous les cas, comme @ejames l'a repéré et souligné dans sa réponse, que voir.

Edit: le code de la deuxième question manque le intdans les deux cas, mais l'ajouter le rend OK, c'est-à-dire:

class A
{
public:
    static int MaxHP;
};
int A::MaxHP = 23;

class Cat: A
{
public:
    static const int MaxHP = 100;
};

fonctionne bien et avec des valeurs différentes pour A :: MaxHP et Cat :: MaxHP - dans ce cas, la sous-classe «n'hérite pas» de la statique de la classe de base, puisque, pour ainsi dire, elle la «cache» avec son propre homonyme une.

Alex Martelli
la source
12
Bonne explication, mais la réponse numérique est en fait 4, pas 3. Voir ma réponse ( stackoverflow.com/questions/998247/… )
e.James
3
+1, Excellent point, je modifie la réponse pour pointer vers la vôtre, merci!
Alex Martelli
1
+1, bien qu'il faille dire plus correctement "+4 à tout ce à quoi le membre statique est initialisé". Le membre statique n'est ni une portée locale ni une portée d'espace de noms, il doit donc y avoir une définition quelque part qui attribue une valeur ( pas nécessairement zéro). Sinon, le code ne remplit pas la règle d'une définition et ne se compilera pas.
Damon
Mais si l'on veut static int totalêtre distinct pour chaque classe dérivée, le seul moyen d'y parvenir est d'ajouter static int totalà chaque classe? Ou est-il possible d'utiliser uniquement la définition de classe de base (?), Car avoir une variable totaldevrait être la propriété de chaque classe. D'un autre côté, ça devrait l'être static.
LRDPRDX
97

La réponse est en fait quatre dans tous les cas, puisque la construction de SomeDerivedClassfera augmenter le total deux fois .

Voici un programme complet (que j'ai utilisé pour vérifier ma réponse):

#include <iostream>
#include <string>

using namespace std;

class SomeClass
{
    public:
        SomeClass() {total++;}
        static int total;
        void Print(string n) { cout << n << ".total = " << total << endl; }
};

int SomeClass::total = 0;

class SomeDerivedClass: public SomeClass
{
    public:
        SomeDerivedClass() {total++;}
};

int main(int argc, char ** argv)
{
    SomeClass A;
    SomeClass B;
    SomeDerivedClass C;

    A.Print("A");
    B.Print("B");
    C.Print("C");

    return 0;
}

Et les résultats:

A.total = 4
B.total = 4
C.total = 4
e.James
la source
10

C'est 4 parce que lorsque l'objet dérivé est créé, le constructeur de classe dérivée appelle le constructeur de classe de base.
Ainsi, la valeur de la variable statique est incrémentée deux fois.

VenuGopal
la source
5
#include<iostream>
using namespace std;

class A
{
public:
    A(){total++; cout << "A() total = "<< total << endl;}
    static int total;
};

int A::total = 0;

class B: public A
{
public:
    B(){total++; cout << "B() total = " << total << endl;}
};

int main()
{
    A a1;
    A a2;
    B b1;

    return 0;
}

Ce serait:

A() total = 1
A() total = 2
A() total = 3
B() total = 4
rocky4android
la source
1

Le constructeur SomeClass () est appelé automatiquement lorsque SomeDerivedClass () est appelé, il s'agit d'une règle C ++. C'est pourquoi le total est incrémenté une fois pour chaque objet SomeClass, puis deux fois pour l'objet SomeDerivedClass. 2x1 + 2 = 4

Darko Maksimovic
la source
0

3 dans les trois cas.

Et pour votre autre question, il semble que vous ayez vraiment besoin d'une variable const au lieu de static. Il peut être plus explicite de fournir une fonction virtuelle qui renvoie la variable dont vous avez besoin qui est remplacée dans les classes dérivées.

À moins que ce code ne soit appelé dans un chemin critique où les performances sont nécessaires, optez toujours pour le code le plus intuitif.

adzm
la source
0

Oui, la classe dérivée contiendrait la même variable statique, c'est-à-dire qu'elles contiendraient toutes 3 pour le total (en supposant que le total a été initialisé à 0 quelque part).

Niki Yoshiuchi
la source