2015-05-04 14 views
50

Aşağıdaki kodu göz önünde bulundurun:Neden bir kullanarak-beyan çalışma elmas problemli m çözmek için geliyor?

struct A 
{ 
    void f() 
    { 
    } 
}; 

struct B1 : A 
{ 
}; 

struct B2 : A 
{ 
}; 

struct C : B1, B2 
{ 
    void f() // works 
    { 
     B1::f(); 
    } 
    //using B1::f; // does not work 
    //using B1::A::f; // does not work as well 
}; 

int main() 
{ 
    C c; 
    c.f(); 

    return 0; 
} 

Ben nazikçe ("sanal devralma kullanmak") elmas sorunu çözmek için nasıl bir standart cevap yapıştırmak kopyalamak değil istiyoruz. Ne ben burada soruyorum bu durumda bir kullanma-beyanname işi yapmaz nedeni budur. Kesin derleyici hatadır: Bir kullanarak-bildirisinin bu örnekten çalışmalıdır izlenimini aldım

In function 'int main()': 
prog.cpp:31:6: error: 'A' is an ambiguous base of 'C' 
    c.f(); 

:

struct A 
{ 
    void f() 
    { 
    } 
}; 

struct B 
{ 
    void f() 
    { 
    } 
}; 

struct C : A, B 
{ 
    using A::f; 
}; 

int main() 
{ 
    C c; 
    c.f(); // will call A::f 

    return 0; 
} 
+0

Geçersiz kılmak için sanal bir yöntem olarak f: – progsource

+4

Hiçbir şeyi geçersiz kılmıyorum. Gizleniyorum. – gd1

+0

[Burada çalışır] (http://coliru.stacked-crooked.com/a/3e301b60717fd4dc). Hangi derleyiciyi kullanıyorsunuz? – 0x499602D2

cevap

56

Birisi standart alıntı bulabilirsiniz ama kavramsal olarak açıklamak için gidiyorum.

bir -bildirge kullanarak çünkü çalışmıyor sadece adı araması etkiler. aksi başarısız olacağını nerede başarılı olmak için ad arama neden

Sizin kullanarak-beyanname, yani o fonksiyonu f bulmak için derleyici söyler. Ancak alt nesnesinin f alteylemlerini, f çağrıldığında örtük this parametresi olarak iletileceğini belirtmez.

C iki A alt nesneler bulunmasına rağmen sadece tek bir işlev A::f vardır ve bu tip A* bir örtük this argüman alır. Bir C nesne üzerinde diyoruz amacıyla, C* örtülü A* dönüştürülmesi gerekir. Bu her zaman belirsizdir ve herhangi kullanarak beyanname etkilenmez.

(Bu A içine veri üyeleri koyarsanız daha mantıklı. Veri üyeleri erişirse Sonra C, denir f her tür veri üyesi iki. Olurdu, bu miras A altnesnesi olanları erişmek yok B2 miras A altnesnesi içinde B1 veya olanları?)

+4

Şimdi, bu konuşuyor. Teşekkürler. – gd1

+0

Yani, kullanma-bildirme yeterince akıllı değil, aksi takdirde A'dan B1'e miras kalanlara erişmelisiniz. – user1633272

28

bu durumu doğrudan hitap/p17 [namespace.udecl] bir not var :

[Not: bir için kullanan-beyan bir temel sınıf elemanı belirtir (ve üye subobject veya bir temel sınıf altnesnesi üyesi fonksiyonu), bir kullanılarak-beyan üye belirsizlikleri kalıtsal gidermek için kullanılabilir olamaz. Örneğin,

struct A { int x(); }; 
struct B : A { }; 
struct C : A { 
    using A::x; 
    int x(int); 
}; 
struct D : B, C { 
    using C::x; 
    int x(double); 
}; 
int f(D* d) {  
    return d->x(); // ambiguous: B::x or C::x 
} 

için - uç not] Başka

+6

Harika, teşekkürler. Bu cevabı kabul etmeye istekliyim, fakat bana sözleriyle ne ifade ettiklerini açıklayabilir misiniz? "Bir taban sınıf üyesi (bir üye alt nesne ya da bir temel sınıf alt nesnesinin üye işlevini değil) belirtir." Ehm ... ne? – gd1

+0

@ T.C. Normatif referans [expr.ref]/5 gibi görünüyor. – Brian

+0

@ gd1 Kullan-bildirimi, bir üye ("A :: x()") belirtir ve bir alt nesneye ('C' veya 'B' (x() ') içeren" B "yi değil. . Belirsizliği gidermek için alt nesneyi belirtmeniz gerekir. – Barry

5

TC cevap ek olarak, ben türetilmiş sınıfta ad arama bölümünde ayrıntılı olarak standardında hemen hemen izah olduğunu eklemek istiyorum 10.2.

10,2/3: arama seti (...) iki bileşenli setler oluşur: beyanı seti, adlandırılmış üyelerin kümesi kullanılarak beyanname işleme konusunda söylenenlerin İşte

f; ve alt-nesne seti, bu üyelerin beyanlarının (muhtemelen bildirimleri de dahil olmak üzere) bulunduğu bir alt nesne kümesidir. Beyan setinde, kullanım bildirimleri, belirttikleri üyeler tarafından değiştirilir ve bildirimler ( enjekte edilmiş sınıf adları da dahil olmak üzere), belirttikleri türlerle değiştirilir. B1::f ve B2::f yüzden hala belirsiz olduğunu:

Yani derleyici yine mümkün adayları bulur arama kurallarına göre struct C

using B1::f; // you hope to make clear that B1::f is to be used 

yılında beyan çalıştığınızda.

+0

Bu, Brian'ın cevabı ile nasıl ilgilidir? – gd1

+0

Brian'ın çok net cevabı aynı zamanda yayınlandı.Eğer onun ilkini okursaydım cevabımı yayınlamamıştım ;-) Ama benimkini silmiyorum, sadece ilgilenen dil avukatları için standart referansı bırakıyorum. – Christophe

+0

Cevabın işe yaramaz olduğunu düşünmüyorum, sadece Brian'ın nasıl olduğunu anlamaya çalışıyorum. Gördüğüm kadarıyla, 10.2/3'ün ne gördüğümü açıklayamadığını görüyorum. ve Brian'ın açıklamaları bana mantıklı geliyor - birlikte kullanıldığında;) – gd1