Статические поля наследуются?

102

Когда статические члены наследуются, являются ли они статическими для всей иерархии или только для этого класса, то есть:

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

всего будет 3 во всех трех случаях, или это будет 2 для SomeClassи 1 для SomeDerivedClass?

БартошКП
источник

Ответы:

55

3 во всех случаях, так как static int totalнаследуется SomeDerivedClassименно входящая SomeClass, а не отдельная переменная.

Изменить: на самом деле 4 во всех случаях, как заметил @ejames и указал в своем ответе, который видит.

Изменить: код во втором вопросе отсутствует intв обоих случаях, но добавление его делает все в порядке, то есть:

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

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

отлично работает и с разными значениями для A :: MaxHP и Cat :: MaxHP - в этом случае подкласс «не наследует» статику от базового класса, так как, так сказать, «скрывает» его своим собственным омонимом один.

Алекс Мартелли
источник
12
Хорошее объяснение, но числовой ответ на самом деле 4, а не 3. См. Мой ответ ( stackoverflow.com/questions/998247/… )
e.James
3
+1, Отличный момент, редактирую ответ, чтобы указать на ваш, спасибо!
Alex Martelli
1
+1, хотя правильнее было бы сказать «+4 к тому, чем инициализирован статический член». Статический член не является ни локальной областью, ни областью пространства имен, поэтому где-то должно быть определение, которое присваивает значение ( не обязательно ноль). В противном случае код не будет соответствовать правилу одного определения и не будет компилироваться.
Дэймон
Но если кто-то хочет static int totalотличаться для каждого производного класса, единственный способ добиться этого - добавить static int totalк каждому классу? Или можно использовать только определение базового класса (?), Потому что наличие переменной totalдолжно быть свойством каждого класса. С другой стороны, так и должно быть static.
LRDPRDX
97

На самом деле во всех случаях ответ будет четыре , так как построение SomeDerivedClassприведет к увеличению суммы в два раза .

Вот полная программа (которую я использовал для проверки своего ответа):

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

И результаты:

A.total = 4
B.total = 4
C.total = 4
е. Джеймс
источник
10

Это 4, потому что при создании производного объекта конструктор производного класса вызывает конструктор базового класса.
Таким образом, значение статической переменной увеличивается вдвое.

ВенуГопал
источник
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;
}

Это было бы:

A() total = 1
A() total = 2
A() total = 3
B() total = 4
rocky4android
источник
1

Конструктор SomeClass () вызывается автоматически при вызове SomeDerivedClass (), это правило C ++. Вот почему сумма увеличивается один раз для каждого объекта SomeClass, а затем дважды для объекта SomeDerivedClass. 2x1 + 2 = 4

Дарко Максимович
источник
0

3 во всех трех случаях.

И для вашего другого вопроса, похоже, вам действительно просто нужна переменная const вместо static. Может быть более очевидным будет предоставить виртуальную функцию, которая возвращает нужную вам переменную, которая переопределяется в производных классах.

Если этот код не вызывается на критическом пути, где необходима производительность, всегда выбирайте более интуитивно понятный код.

АДЗМ
источник
0

Да, производный класс будет содержать одну и ту же статическую переменную, т. Е. Все они будут содержать 3 в сумме (при условии, что сумма где-то инициализирована равной 0).

Ники Ёсиучи
источник