代码之家  ›  专栏  ›  技术社区  ›  dEmigOd

类层次结构中的运算符重载解析

  •  2
  • dEmigOd  · 技术社区  · 7 月前

    我有一个等级制度 operator() 重载如下

    class Base{
    public:
        virtual std::vector<float> operator()(const std::vector<float>& us) const {
            // some implementation like
            // return us;
        }
    
        virtual float operator()(float u) const = 0;
    };
    

    以及一个派生类

    class Derived : public Base{
    public:
        float operator()(float u) const override {
            return u;
        }
    };
    

    调用代码看起来像下面的代码(假设 GetAVectorOfFloats 第二个确实 std::vector 属于 float s

    Derived d;
    auto [_, us] = GetAVectorOfFloats();
    auto values = d(us);
    
    

    然而,编译器(gcc版本11.4.0(Ubuntu 11.4.0-1ubuntu1~22.04)

    错误:对(Derived)(std::vector&)的调用不匹配

    我观察到 const std::vector<float>& 这不是一种选择(但为什么呢?)。

    如果代码更明确

    auto values = d.operator()(us);
    

    误差变为

    错误:无法转换std::vector<浮动>漂浮

    好像我错过了一些非常基本的东西?我不能调用Base的运算符()吗?或者我应该使用一些特殊的语法吗?

    2 回复  |  直到 7 月前
        1
  •  3
  •   user17732522    7 月前

    这是经典的名称隐藏,运算符重载没有什么特别之处:

    查找名称时 operator() 已完成 Derived (因为这是一种 d )它发现 float operator()(float u) const; .

    然后,名称查找终止,因为已找到该名称。将不会进一步查找基类。

    解决方案是使另一个重载在派生类的范围内对名称查找可见:

    class Derived : public Base{
    public:
        using Base::operator();
        float operator()(float u) const override {
            return u;
        }
    };
    
        2
  •  1
  •   Levente Bokor    7 月前

    您遇到此问题的原因是 姓名隐藏 .

    如果你超载,你可能会看到 也不 如果运算符不是纯虚的,那么这两个运算符在派生类中都能很好地工作。

    因为你只是超载了 在操作员中,另一个实际上是隐藏的,因为它不是直接的一部分 Derived .

    为了克服这个问题,您可以重载两个运算符,或者显式地引入 Base 类运算符作用域:

    class Derived : public Base {
    public:
        using Base::operator();
    
        float operator()(float u) const override {
            return u;
        }
    };