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


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

1

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


0

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

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

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


0

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.