cRTP

2016-06-08 28 views
5

kullanırken derleyici temel sınıf yöntemi görmez Neden aşağıdaki kod parçası var:cRTP

struct Iface 
{ 
    virtual int Read() = 0; 

    int Read(int x) { 
     return Read() + x; 
    } 
}; 

template <typename Impl> 
struct Crtp : public Iface 
{ 
    virtual int Read() { 
     return static_cast<Impl&>(*this).ReadImpl(); 
    } 
    //using Iface::Read; 
}; 

struct IfaceImpl : public Crtp<IfaceImpl> 
{ 
    int ReadImpl() { 
     return 42; 
    } 
}; 

int main() 
{ 
    IfaceImpl impl; 
    impl.Read(24); // compilation error 

    Iface& iface = impl; 
    iface.Read(24); // always compiles successfully 
} 

İkisi msvc, gcc, clang bu kodu reddetmek, onlar bulamıyor yöntem Read(int x)

Ancak Crtp içinde using Iface::Read uncomment eğer kodum başarılı bir şekilde derler. Ben Iface bir başvuru atarsan Read(int x)

Bunun nedeni nedir diyoruz ki

Not?

cevap

7

Bu neden oluyor?

Sorununuzun CRTP ile ilgisi yoktur. Normal miras senaryosunda meydana gelebilecek bir isim gizleme sorunu.

impl.Read(24); numaralı telefonu aradığınızda, Read üye işlev adı IfaceImpl sınıf kapsamında bulunamaz. Daha sonra Crtp taban sınıfının kapsamı incelenecek ve orada Read ismi bulunacaktır. Daha sonra arama durur, bu nedenle Iface diğer baz sınıfında int Read(int x), burada daha uygun olsa bile, aşırı yük çözünürlüğü için dikkate alınmayacaktır.

using Iface::Read; tarafından Read adının Crtp sınıf kapsamına tanıtılıyor. Daha sonra, aşırı yük çözünürlüğü doğru bir şekilde bulunup seçilebilir.

Ve eğer Iface referansı ile çağırırsanız, ad arama işlemi iyi sonuç verecektir. Veya impl.Iface::Read(24); tarafından açıkça (ve çirkin) tarafından çağırabilirsiniz.

Unqualified name lookup bakınız: bu arama durdurur ve bir daha kapsamları incelendiğinde bu süre içinde herhangi bir en az bir bildiri, bulana kadar, aşağıda tarif edildiği gibi

... adı arama kapsamları inceler.