簡體   English   中英

為什么編譯器在使用CRTP時看不到基類的方法

[英]Why compiler does not see method of base class when using 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
}

msvc,gcc和clang都拒絕這段代碼,他們找不到方法Read(int x)

但是,如果我在Crtp using Iface::Read取消注釋,我的代碼將成功編譯。

請注意,如果我參考Iface,我可以調用Read(int x)

為什么會這樣?

為什么會這樣?

您的問題與CRTP無關。 這是在正常繼承方案中可能發生的名稱隱藏問題。

當你調用impl.Read(24); ,在IfaceImpl的類范圍內找不到成員函數名Read 然后將檢查基類Crtp的范圍,並在那里找到名稱Read 然后名稱查找停止,因此在另一個基類Iface中的int Read(int x)將不會被考慮用於重載解析,即使它在這里更合適。

通過using Iface::Read; 你將名稱Read引入Crtp的類范圍。 然后可以通過正確的重載分辨率找到並選擇它。

如果你通過Iface引用調用它,名稱查找將很好。

或者你可以通過impl.Iface::Read(24);顯式地(和丑陋地)調用它impl.Iface::Read(24);

請參閱非限定名稱查找

... name lookup檢查范圍如下所述,直到它找到至少一個任何類型的聲明,此時查找停止並且不再檢查其他范圍。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM