c++ - 为什么编译器在使用 CRTP 时看不到基类的方法

标签 c++ inheritance 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)

为什么会这样?

最佳答案

Why does this happen?

您的问题与 CRTP 无关。这是在正常的继承场景中可能发生的名称隐藏问题。

调用impl.Read(24);时,IfaceImpl类作用域内找不到成员函数名Read >。然后将检查基类 Crtp 的范围,并在那里找到名称 Read。然后名称查找停止,因此进一步基类 Iface 中的 int Read(int x) 不会被考虑用于重载解析,即使它在这里更合适。

通过 using Iface::Read;,您将名称 Read 引入到 Crtp 的类作用域中。然后可以通过重载解析正确地找到和选择它。

如果您通过 Iface 引用调用它,名称查找将正常工作。

或者您可以通过 impl.Iface::Read(24); 显式地(丑陋地)调用它。

参见 Unqualified name lookup :

... name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.

关于c++ - 为什么编译器在使用 CRTP 时看不到基类的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37696703/

相关文章:

c++ - 'using'指令如何与模板成员函数一起工作

c++ - 不同时间段的计时?

c++ - 如何使用 Gradle 的 cpp-library 和 cpp-application 插件指定自定义 GCC/G++ 编译器位置?

c++ - 密集和稀疏矩阵的高效(时间和空间复杂度)数据结构

c++ - 关于C++中bool的问题

inheritance - 内联私有(private)和 protected 虚函数调用

python - 子类中 __slots__ 的继承实际上是如何工作的?

C++ "was not declared in this scope"在派生类中覆盖纯虚方法时

arrays - 如何向对象数组添加一个继承的对象? ( swift ,XCode)

c++ - CRTP 失败 w/decltype