Statik alanlar miras alınıyor mu?


102

Statik üyeler miras alındığında, tüm hiyerarşi için statik mi yoksa sadece o sınıf için mi?

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

her üç durumda da toplam 3 olur, yoksa 2 için SomeClassve 1 için 1 olur SomeDerivedClassmu?

Yanıtlar:


55

Her durumda 3, çünkü static int totaltarafından miras alınan , farklı bir değişken değil SomeDerivedClass, tam olarak içeride olanıdır SomeClass.

Düzenleme: Aslında her durumda 4 , @ejames tespit ettiği ve cevabında işaret ettiği gibi, gördünüz mü?

Düzenleme: ikinci sorudaki kod inther iki durumda da eksiktir , ancak eklenmesi sorunu çözer, yani:

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

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

iyi çalışır ve A :: MaxHP ve Cat :: MaxHP için farklı değerlerle çalışır - bu durumda alt sınıf, statik olanı temel sınıftan "miras almamaktadır", çünkü tabiri caizse, onu kendi homonimiyle "gizlemektedir". bir.


12
İyi bir açıklama, ancak sayısal cevap aslında 4'tür, 3 değil.
Cevabıma

3
+1, Mükemmel nokta, cevabı sizinkini gösterecek şekilde düzenliyorum, teşekkürler!
Alex Martelli

1
+1, ancak daha doğru bir şekilde "Statik üye başlatılan her şeye +4" demelidir. Statik üye ne yerel kapsam ne de ad alanı kapsamıdır, bu nedenle bir yerde değer atayan bir tanım olmalıdır ( mutlaka sıfır değildir ). Aksi takdirde kod tek tanım kuralını yerine getirmez ve derlenmez.
Damon

Ancak static int total, her bir türetilmiş sınıf için farklı olmak istiyorsa , onu static int totalher sınıfa eklemenin tek yolu nedir? Veya yalnızca temel sınıf tanımını (?) Kullanmak mümkün müdür, çünkü değişkene sahip totalolmak her sınıfın özelliği olmalıdır. Öte yandan olmalı static.
LRDPRDX

97

Cevap aslında her durumda dörttür , çünkü inşası SomeDerivedClasstoplamın iki kez artmasına neden olacaktır .

İşte eksiksiz bir program (cevabımı doğrulamak için kullandığım):

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

Ve sonuçlar:

A.total = 4
B.total = 4
C.total = 4

10

4'tür çünkü türetilmiş nesne oluşturulduğunda, türetilmiş sınıf yapıcısı temel sınıf yapıcısını çağırır.
Böylece statik değişkenin değeri iki kez artırılır.


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

Olurdu:

A() total = 1
A() total = 2
A() total = 3
B() total = 4

1

BazıClass () yapıcısı, SomeDerivedClass () çağrıldığında otomatik olarak çağrılır, bu bir C ++ kuralıdır. Bu nedenle toplam, her SomeClass nesnesi için bir kez ve daha sonra SomeDerivedClass nesnesi için iki kez artırılır. 2x1 + 2 = 4


0

Her üç durumda da 3.

Ve diğer sorunuz için, gerçekten statik yerine bir const değişkenine ihtiyacınız var gibi görünüyor. Türetilmiş sınıflarda geçersiz kılınan, ihtiyacınız olan değişkeni döndüren sanal bir işlevi sağlamak için daha açıklayıcı olabilir.

Bu kod, performansın gerekli olduğu kritik bir yolda çağrılmadıkça, her zaman daha sezgisel kodu tercih edin.


0

Evet, türetilmiş sınıf aynı statik değişkeni içerecektir, yani hepsi toplam için 3 içerecektir (toplamın bir yerde 0 olarak başlatıldığı varsayılarak).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.