Neden static
sınıftaki veri üyelerini başlatamıyorum ?
C ++ standardı yalnızca statik sabit integral veya numaralandırma türlerinin sınıf içinde başlatılmasına izin verir. Bu nedenle a
, diğerlerinin başlatılmasına izin verilmiyor.
Referans:
C ++ 03 9.4.2 Statik veri üyeleri
§4
Bir statik veri üyesi, const integrali veya sabit numaralandırma türündeyse, sınıf tanımındaki bildirimi, bir integral sabit ifadesi (5.19) olacak bir sabit başlatıcıyı belirtebilir. Bu durumda üye, integral sabit ifadelerde görünebilir. Üye, programda kullanılıyorsa yine de bir ad alanı kapsamında tanımlanacaktır ve ad alanı kapsam tanımı bir başlatıcı içermeyecektir.
İntegral türleri nelerdir?
C ++ 03 3.9.1 Temel türler
§7
Bool, char, wchar_t türleri ve işaretli ve işaretsiz tamsayı türleri topluca integral türleri olarak adlandırılır.43) İntegral türünün eşanlamlısı, tamsayı türüdür.
Dipnot:
43) Bu nedenle, numaralandırmalar (7.2) integral değildir; ancak, numaralandırmalar, 4.5'te belirtildiği gibi int, unsigned int, long veya unsigned long olarak yükseltilebilir.
Çözüm:
Sınıf tanımınızın içinde bir diziyi başlatmak için enum numarasını kullanabilirsiniz .
class A
{
static const int a = 3;
enum { arrsize = 2 };
static const int c[arrsize] = { 1, 2 };
};
Standart buna neden izin vermiyor?
Bjarne bunu uygun bir şekilde burada açıklıyor :
Bir sınıf genellikle bir başlık dosyasında bildirilir ve bir başlık dosyası genellikle birçok çeviri birimine dahil edilir. Ancak, karmaşık bağlayıcı kurallarından kaçınmak için, C ++ her nesnenin benzersiz bir tanıma sahip olmasını gerektirir. C ++, bellekte nesneler olarak depolanması gereken varlıkların sınıf içi tanımına izin verirse, bu kural bozulur.
Neden yalnızca static const
integral türlerine ve numaralandırmalara Sınıf İçi Başlatma'ya izin verilir?
Cevap, Bjarne'nin sözünde gizli, yakından okuyun,
"C ++ her nesnenin benzersiz bir tanıma sahip olmasını gerektirir. C ++, bellekte nesne olarak depolanması gereken varlıkların sınıf içi tanımına izin verirse bu kural bozulur."
Yalnızca static const
tam sayıların derleme zamanı sabitleri olarak değerlendirilebileceğini unutmayın. Derleyici, tamsayı değerinin hiçbir zaman değişmeyeceğini bilir ve bu nedenle kendi sihrini uygulayabilir ve optimizasyonları uygulayabilir, derleyici bu tür sınıf üyelerini satır içine alır, yani artık bellekte depolanmaz, bellekte depolanma ihtiyacı ortadan kalktıkça , bu tür değişkenlere Bjarne tarafından bahsedilen kuralın istisnasını verir.
Burada, static const
integral değerlerin Sınıf İçi Başlatma'ya sahip olabilmesine rağmen, bu tür değişkenlerin adreslerinin alınmasına izin verilmediğini belirtmek önemlidir . Statik bir üyenin adresi sınıf dışı bir tanıma sahipse (ve ancak) alınabilir. Bu, yukarıdaki gerekçeyi daha da doğrular.
numaralandırılmış türden değerler, girişlerin beklendiği yerde kullanılabileceğinden, buna izin verilir. yukarıdaki alıntıya bakın
Bu C ++ 11'de nasıl değişiyor?
C ++ 11, kısıtlamayı bir ölçüde gevşetir.
C ++ 11 9.4.2 Statik veri üyeleri
§3
Statik veri elemanı const hazır türdeyse, sınıf tanımında da bildirimi bir belirtebilir bağ ya da-eşit-başlatıcı her hangi başlatıcı-maddesi , bir olan atama-sentezleme sabit bir ifadesidir. Değişmez türden bir statik veri üyesi, sınıf tanımında, constexpr specifier;
eğer öyleyse, bildirimi , bir atama ifadesi olan her başlatıcı cümlesinin bulunduğu bir parantez veya eşitleme başlatıcısı belirtmelidir.sabit bir ifadedir. [Not: Her iki durumda da üye sürekli ifadelerde görünebilir. —Son notu] Üye, programda kullanılıyorsa yine de bir ad alanı kapsamında tanımlanacaktır ve ad alanı kapsam tanımı bir başlatıcı içermeyecektir.
Ayrıca, C ++ 11 , statik olmayan bir veri üyesinin (kendi sınıfında) bildirildiği yerde başlatılmasına (§12.6.2.8) izin verecektir. Bu, çok kolay kullanıcı semantiği anlamına gelecektir.
Bu özelliklerin en son gcc 4.7'de henüz uygulanmadığına dikkat edin. Bu nedenle, derleme hataları almaya devam edebilirsiniz.