SORU
2 Temmuz 2013, Salı


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
2 Temmuz 2013, Salı


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()).

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • gsmaestro

    gsmaestro

    17 AĞUSTOS 2006
  • jpmkm1

    jpmkm1

    4 NİSAN 2008
  • Max Lee

    Max Lee

    18 AĞUSTOS 2006