Hata kullanırken sınıfının statik olmayan başlatma veri üyesi ve iç içe geçmiş bir sınıf yapıcısı
Aşağıdaki kod oldukça basit ve güzel bir derleme gerektiğini beklerdim.
struct A
{
struct B
{
int i = 0;
};
B b;
A(const B& _b = B())
: b(_b)
{}
};
G sürümü ile bu kodu 4.7.2, 4.8.1 tin 3.2 ve 3.3 test ettim. G 4.7.2 bu kod üzerinde segfaults bu gerçeği (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57770) dışında, diğer test Derleyiciler fazla açıklama yapmana gerek yok hata iletileri ver.
g 4.8.1:
test.cpp: In constructor ‘constexpr A::B::B()’:
test.cpp:3:12: error: constructor required before non-static data member for ‘A::B::i’ has been parsed
struct B
^
test.cpp: At global scope:
test.cpp:11:23: note: synthesized method ‘constexpr A::B::B()’ first required here
A(const B& _b = B())
^
3.2 ve 3.3 çınlama:
test.cpp:11:21: error: defaulted default constructor of 'B' cannot be used by non-static data member initializer which appears before end of class definition
A(const B& _b = B())
^
Bu kod derlenebilir yapmak mümkün değildir ve hiçbir fark yapmak gerekir gibi görünüyor. İki seçenek vardır:
struct B
{
int i = 0;
B(){} // using B()=default; works only for clang
};
ya
struct B
{
int i;
B() : i(0) {} // classic c 98 initialization
};
Bu gerçekten yanlış kod veya Derleyiciler yanlış mı?
CEVAP
Bu gerçekten yanlış kod veya Derleyiciler yanlış mı?
De. Standart bir kusur. hem o A
kabul tamamlarken ayrıştırma başlatıcısı için B::i
B::B()
(kullandığı başlatıcısı için B::i
) kullanılabilir içinde tanımı A
. Açıkça döngüsel. Bu göz önünde bulundurun:
struct A {
struct B {
int i = (A(), 0);
};
A() noexcept(!noexcept(B()));
};
Bu bir çelişki vardır: B::B()
örtülü olarak ıff A()
atmaz ıff noexcept
ve A()
ıff B::B()
atmak değildeğilnoexcept
. Bu alanda diğer döngüleri ve çelişkiler vardır.
Bu temel sorunlar 1360 1397 tarafından izlenir. Özellikle not bu temel sorun 1397 not:
Belki de bu ele en iyi yolu, statik olmayan veri üyesi başlatıcısı kendi sınıfının varsayılan yapıcı kullanmak için kötü biçimlendirilmiş yapmak olacaktır.
Bu Şıngırtıyı bu sorunu gidermek için uygulanan bu kural özel bir durum. Çınlama kuralı bir sınıf için varsayılan varsayılan bir kurucusu olan sınıfın statik olmayan veri üyesi başlatıcılar ayrıştırıldı önce kullanılır. Dolayısıyla Çınlama sorunları bir tanı burada:
A(const B& _b = B())
^
... çünkü Çınlama ayrıştırır varsayılan argümanlar önce ayrıştırır varsayılan başlatıcı, ve bu varsayılan argüman gerektirecek; B
'In varsayılan başlatıcı için zaten ayrıştırılmış (sipariş için örtülü olarak tanımlamak B::B()
).
C statik sabit dize (sınıf üyesi)...
hata: üye '..' olmayan bir s...
::push_back vector) kullanır değeri, s...
Java statik iç içe geçmiş bir sınıf, n...
C : sınıf veri üyesi için İşaretçi...