C++ 编译器 (cl) 看不到具有相同子方法名称的父虚方法

C++ Compiler (cl) does not see parent virtual method with same child method name

我有一个C++代码,同时使用了继承和函数覆盖,代码如下:

#include <iostream>
#include <string>

using namespace std;

class Parent
{
    protected:
        virtual void G() const = 0;
    public:
        virtual void G(const string& s) const final { G(); }
};

class Child : public Parent
{
    protected:
        virtual void G() const override { cout<<"Child G"; }
};

int main()
{
    Child *c = new Child();
    c->G("test");
    return 0;
}

编译时出现错误:Child::G: function does not take 1 arguments。但是当我像这样使用 Parent 指针时:

Parent *c = new Child();

有效。或者,如果我更改 public G 方法的名称,它也可以工作。

两种方法使用相同的名称 (G) 有什么问题?

您需要通过 using 声明将父成员引入子成员:

class Child : public Parent
{
    protected:
        virtual void G() const override { cout<<"Child G"; }
    public:
        using Parent::G;
};

解决这个问题的方法确实是将 Parent 的方法引入 Child class 的范围,并带有 using 声明,@Jans 好心指出。至于 为什么 是这种情况,这只是编译器在搜索与您的函数调用匹配的方法时如何搜索作用域的问题。发生的事情的分解如下:

  • Child *c = new Child(); c->G("test"); 中,编译器看到对 Child 类型对象上的某个方法 G 的调用。然后搜索 Child 的范围以查找匹配项。
  • 编译器在探索 Child 的范围时,只看到 Child::G() const。它Parent::G(const std::string&) const,即使您希望通过继承将其包括在内,它也处于不同的范围。从某种意义上说,Child::G遮蔽Parent::G。如果没有候选匹配项,编译器将继续搜索 Parent 范围。
  • 编译器很高兴找到 Child::G。但是,这是一个不接受任何参数的函数,而您试图用 "test" 调用它。由于参数不匹配,函数调用随后失败。

如前所述,您需要将 Parent::G 放入与 Child::G 相同的范围内,以便按预期进行重载,using Parent::GChild 的主体内。

来源:https://isocpp.org/wiki/faq/strange-inheritance#overload-derived