c++ - 是否可以强制父类(super class)中的非 const 虚方法优先于子类中同名的 const 方法?

标签 c++ oop constants

考虑以下类定义:

class foo {
  virtual absl::Span<const Input *const> GetInputs() const = 0;

  virtual absl::Span<Input *const> GetInputs() {
    auto mutable_inputs = GetMutableInputs();
    return absl::MakeSpan(mutable_inputs.begin(), mutable_inputs.end());
  }
}

class bar : public foo {
  absl::Span<const Input *const> GetInputs() const override {
    return absl::MakeConstSpan(inputs_);
  }
}

调用 bar.GetInputs() 时,似乎唯一找到的实现是返回一系列常量输入的实现。如果我有一个 bar 实例,并且想要创建一个非常量输入范围,那么我必须将 bar 转换为 foo,然后调用 GetInputs

如果我将 bar 转换为 foo,然后调用 GetInputs,我就可以将结果分配给一系列非常量输入。为什么编译器无法识别具有正确返回类型的继承的非常量方法?有没有办法让子类识别那个方法?

换句话说,有没有办法让下面的代码通过编译:

absl::Span<Input *const> tmp = bar.GetInputs()

最佳答案

如果我理解你的问题,它与虚函数或 const 的“优先级”无关,而是普通的“名称隐藏”。

#include <iostream>
class Base {
public:
    virtual void f(int)    { std::cout << "Base(int)\n"; }
    virtual void f(double) { std::cout << "Base(double)\n"; }
};

class Derived : public Base {
public:
    virtual void f(double) { std::cout << "Derived(double)\n"; }
};

int main() {
    Derived d;
    int x=0;
    d.f(x);
}

输出:派生(双)

问题是,名称查找并不像您期望的那样工作。 对于给定范围,它搜索名称以构建重载集。在 Derived 的上下文中,只有一个 f(),因此当找到它时,编译器停止进一步搜索更多重载

它找到 Derived(double) 并且这是整个重载集,因此它被选中。当您将派生类转换为对基类的引用,然后调用某些内容时,会考虑两个函数(在基类中声明),并且重载决策会选择最佳匹配。

现在,通常,对于多态类型,您是根据指向基的指针/引用来处理对象,因此这不是问题。但是,如果您直接调用派生类(可能是从派生类的成员内部调用?),那么派生类声明会隐藏基本名称。

要使基名在派生类中可见,很简单:

class Derived : public Base {
public:
    using base::f; // <<<<<<<< just add this
    virtual void f(double) { std::cout << "Derived(double)\n"; }
};

关于c++ - 是否可以强制父类(super class)中的非 const 虚方法优先于子类中同名的 const 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49759998/

相关文章:

c++ - 这个C++指针使用线程安全吗?

swift - 我应该在类内部实现函数来适应 MVC 吗?

iphone - 在运行时修改 objective-c 中的常量

c++ - 类中私有(private)静态方法和私有(private)方法之间的区别

c++ - 将 std::string 转换为 char *

c++ - 编程语言开发实践,如何将golang风格的接口(interface)编译为c++?

c++ - 自定义流对象错误?

oop - 何时将方法声明为私有(private)

php - 所有用户中显示用户注销

c++ - 为什么带有 const 关键字的构造函数可以工作,而没有它就不行?