繁体   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