【问题标题】:Overriding method shadows overloaded final version覆盖方法阴影重载最终版本
【发布时间】:2022-01-21 12:22:55
【问题描述】:

我有以下代码:

struct Abs {
    virtual void f(int x) = 0;
    virtual void f(double x) final { std::cout << 2; }
};

struct Sub: public Abs {
    void f(int x) final { std::cout << 1; }
};

Abs 是一个抽象类,它包含一个纯成员函数void f(int) 及其重载版本void f(double x),它不再是纯成员函数final。如果我尝试在派生结构Sub 中覆盖void f(int),它会遮蔽void f(double),下面的main 函数会打印1,将1.01 转换为int

int main() {
    Sub x = {};
    x.f(1.01);
    return 0;
}

我该如何克服这个问题?还有,为什么会这样?

【问题讨论】:

  • 它是这样工作的,因为标准要求它这样做。查找“隐藏规则”。它不仅适用于类 - 它也适用于嵌套范围。在您的情况下,“修复”是让Sub 类有一行using Abs::f,这会在Sub 的上下文中调用f() 时使Abs::f() 的两个版本成为候选对象。跨度>
  • 您可以将参数括在大括号中,并且将禁止隐式转换。这样您就可以事先了解如何将 double 缩小为 int。

标签: c++ inheritance overriding overloading abstract-class


【解决方案1】:

给定x.f(1.01);,名称f在类Sub的范围内,然后name lookup停止;不会检查Abs 的范围。只有Sub::f 会被放入重载集,然后执行重载解析。

...名称查找检查如下所述的范围,直到找到至少一个任何类型的声明,此时查找停止并且不再检查范围。

您可以使用usingAbs的名称引入Sub,然后Abs::f也可以被找到并参与重载解析。

struct Sub: public Abs {
    using Abs::f;
    void f(int x) final { std::cout << 1; }
};

【讨论】:

    【解决方案2】:

    您必须将using 子句添加到派生类中才能从基类中挑选所有重载。

    struct Abs {
        virtual void f(int x) = 0;
        virtual void f(double x) final {std::cout << 2;} 
    };
    
    struct Sub: public Abs {
        using Abs::f;   // << this one did the trick
        void f(int x) final { std::cout << 1; }
    };
    
    int main() {
        Sub x = {}; 
        x.f(1.01);
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2015-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-13
      • 1970-01-01
      • 1970-01-01
      • 2012-04-02
      • 1970-01-01
      相关资源
      最近更新 更多