Derived1 :: Base ve Derived2 :: Base aynı türe mi işaret ediyor?


12

MSVC, Clang ve GCC bu koda katılmıyor:

struct Base { int x; };
struct Der1 : public  Base {};
struct Der2 : public  Base {};

struct AllDer : public Der1, public Der2 {
    void foo() {
        Der1::Base::x = 5;
    }
};

Godbolt

GCC:

<source>: In member function 'void AllDer::foo()':    
<source>:10:21: error: 'Base' is an ambiguous base of 'AllDer'    
   10 |         Der1::Base::x = 5;    
      |                     ^    
Compiler returned: 1

Clang benzer bir hata verir ve MSVC hiçbir hata vermez.

Tam burada kim?

Sanırım bu [class.member.lookup] ' da ele alınmaktadır , ancak bu dava için bana ne anlatmaya çalıştığını anlamakta zorlanıyorum. Lütfen ilgili parçaları belirtin ve mümkünse açık İngilizce olarak açıklayın.

Not: Bu sorudan esinlenilmiştir Neden Temel Sınıfa Referans :: -operator türetilmiş sınıfla neden belirsizdir?

PPS: Aslında benim kuşkum, Der1::Basetipe atıfta bulunulması, bu tip Base(ve sonra Der2::Basetam olarak aynı tip) veya alt nesneye atıfta bulunulmasıdır . Ben ilk olduğuna ikna oldum, ancak ikincisi ise MSVC doğru olurdu.



@LanguageLawyer, gcc ve clang'ın doğru olduğuna dair daha iyi ipuçları, ancak mscv'nin yanlış olduğuna tamamen ikna olmadım
idclev 463035818

1
Açıkçası her ikisi de aynı türden bahsediyor ::Base, ancak asıl soru burada biraz farklı görünüyor. İki tür alt nesne vardır Baseve her ikisinin de bir Base::x üyesi vardır.
MSalters

@MSPers sadece karışıklığımı ifade eder. Daha iyi bir başlık için bir öneriniz varsa, çekinmeyin (kendimi sevmiyorum (cevabın evet olduğunu biliyorum), ancak daha uygun bir şey bulamadım
idclev 463035818

1
@ d4rk4ng31 kodda sanal bir miras yok (bilerek)
idclev 463035818

Yanıtlar:


6

Başlıktaki soruyu cevaplamak için, Evet, Derived1::Basereferanslar enjekte sınıf-ad [class.pre] Base öylesine ve yapar Derived2::Base. Her ikisi de sınıfa atıfta bulunur ::Base.

Şimdi, statik bir üye Baseolsaydı , o zaman araması net olur. Sadece biri var.xBase::x

Bu örnekteki sorun, xstatik olmayan bir üye olması ve AllDerbu tür iki üyesi olmasıdır. Yalnızca bir üyesi olan açık bir temel sınıf xbelirterek bu erişimi kesinleştirebilirsiniz . açık bir temel sınıftır ve bir üyesi vardır, bu yüzden açık bir şekilde iki üyeden hangisini kastettiğinizi belirtir . sadece bir üyesi vardır, ama bunun açık bir temeli değildir . Her örneğinde iki tür alt nesne vardır . Bu nedenle örneğinizde belirsiz. Ve sadece başka bir isim olduğu için , bu belirsizliğini koruyor.AllDerxDerived1xDerived1::xxAllDerBasexAllDerAllDerBaseBase::xDerived1::BaseBase

[class.member.lookup] x, yuvalanmış ad belirteci bağlamında aranacağını belirtir, bu nedenle önce çözülmesi gerekir. Gerçekten arıyoruz Base::x, değil Derived1::x, çünkü Derived1::Baseolarak çözerek başladık Base. Bu bölüm başarılı olur, [class.member.lookup] 'da Not 12'de yalnızca bir tanesi x, Base.açıkça aynı ada sahip birden çok alt nesne olduğunda açık bir isim aramasının kullanılmasının yine de başarısız olabileceğini söyler. D::ibu örnekte temelde sizin Base::x.


yani sadece "başarısız olabilir" ama "başarısız" değil ve üç derleyici de doğru mu? Örneğin a için düşünün template <typname A,typename B> struct foo : A,Bbir temelinin erişim üyelerine bazı suni kodla Ave B. Bu durumda bir hata almak istiyorum
idclev 463035818

1
@ idclev463035818: Bunun bir "başarısız olmalı" tanılaması gerektiğinden şüpheleniyorum . Özellikle, bu 7.6.1.4/7 "kötü biçimlendirilmiş" Sınıf üyesi erişim başarısız.
MSalters

Biraz daha okuma yapmak zorundayım. Ve msvc üzerinde biraz araştırma yapmak zorundayım, tamamen uyumlu çıktı almak için bazı bayraklara ihtiyaç duyulduğundan şüpheleniyorum, ancak hangi bayrakları bulmak zorundayım
idclev 463035818

2

Sınıf adına sınıfın bir üyesi olarak başvurabilmenizin nedeni, cpp'nin using Base = ::Base;Base içinde yazmış gibi rahat kullanım için takma olmasıdır .
Karşılaştığınız sorun Der1::Baseşu Base.
Böylece, yazdığınızda Der1::Base::x, aynıdır Base::x.


"Sorun" nedir biliyorum ama soruma cevap vermiyorsun: "Kim haklı? (Ve neden?)"
idclev 463035818

@ idclev463035818: Bunun doğru taraf olduğuna inanıyorum. Hakkında kısım usingstandartta yazılmıştır ve bence bu ifadenin söylediklerini yorumlamanın anahtarıdır.
Dani

@ idclev463035818: Aşağıdaki örneğe bakın. Sanırım biraz temizleyecek. ideone.com/IqpXjT
Dani

üzgünüm ama sanırım sorumun anlamını alamadın. Standarda göre neyin doğru olduğunu bilmek istiyorum, çünkü farklı derleyicilerin farklı şeyler yaptığını görüyorum. Belirli bir derleyicinin belirli bir örneğe ne yaptığını görmek, soruyu cevaplamaya yardımcı olmaz
idclev 463035818

Sadece FYI, MSVC (x64 için 19.25.28614 sürümü) örneğinizi ideone.com/IqpXjT adresinde derleyemez . cl /c /Wall /WX /Od /MDd /Za /permissive- /std:c++17 main.cppKomut satırı olarak kullanarakmain.cpp(7): error C2597: illegal reference to non-static member 'A::x'
heap underrun
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.