【问题标题】:Why Am I Unable to Override Virtual Function?为什么我无法覆盖虚拟功能?
【发布时间】:2020-04-01 07:55:48
【问题描述】:

我试图覆盖 Vector_container 中的 size 函数,但 IDE 告诉我“标记为‘覆盖’的非虚拟成员函数隐藏了虚拟成员函数”

class Container {
public:
    virtual double& operator[](int) = 0;     // pure virtual function
    virtual int size() const = 0;            // const member function (§4.2.1)
    virtual ~Container() {}                  // destructor (§4.2.2)
};


class Vector_container : public Container {   // Vector_container implements Container
public:
    Vector_container(int s) : v(s) { }   // Vector of s elements
    ~Vector_container() {}

    double& operator[](int i) override { return v[i]; }
    int size() override { return v.size(); }
private:
    Vector v;
};

但它不是虚函数吗?

【问题讨论】:

  • 基类中的虚函数不同。它是常量
  • 函数可以通过标记const来重载。
  • 不相关:容器的size() 函数应该返回size_t 而不是int
  • 太烦人了。编译器正确地识别问题并提出警告(显然警告被视为错误),但警告是如此无用,以至于让用户感到困惑。输出带有警告的int size() hides int size() **const** 会花费多少额外费用,这样不知情的用户就不会浪费半个小时来想知道出了什么问题?
  • 我正在使用 XCode,先生。

标签: c++ inheritance polymorphism overriding constants


【解决方案1】:

在这里,一致性很重要。你的Container 声明一个纯虚拟的int size() const,而你试图覆盖int size()。根据我的测试,将您的覆盖声明为 const works

【讨论】:

  • 如果我将其更改为 int size() const override { return v.size();它告诉我“成员函数‘size’的‘this’参数的类型为‘const Vector’,但函数未标记为const”
  • @Lester 如果你写了Vector::size,那么你可能也应该标记const
  • 哇。谢谢你帮我检查。不知道这里发生了什么! :)
  • @Lester 没问题,@George 感谢您的注意;我的测试假设 Vector 有一个 const 大小,因为我用 std::vector 将它存根。
【解决方案2】:

正如其他人提到的,使用 const 会改变函数的签名。我想添加更多的知识花絮,以帮助将来的其他人。

在 C++ 中覆盖函数时,如果您的编译器支持 C++11 及更高版本,请在函数签名末尾使用 override 关键字。这将从编译器中产生更多有用的信息。如果虚函数有一个 override 关键字,编译器可能会导致程序在编译时失败。如果编译器找不到具有相同函数签名的父虚函数来覆盖,则会发生错误。与运行时相比,在编译时捕获错误几乎总是更好。

看起来好像您使用了 override 关键字,因此它可能为您指明了正确的方向。我要强调这一点的主要原因是我希望看到此问题的其他人意识到您可以在编译时使用该关键字捕获错误的覆盖。

人们在工业中的一个常见做法是提供一个带有和不带有 const 的基本函数。虽然许多人可能会说这违背了 const 的目的,但在某些情况下,您可能需要在非常量函数或非常量对象上调用 const 函数。唯一的另一种选择是使用可变的,我发现较少的 C++ 程序员理解其含义。

简而言之,const 改变了函数的签名,因此只有在 const 签名匹配的情况下才能在子类上被覆盖。

这是一个类似问题的链接,它更深入地介绍了 const 和函数签名。它还深入研究了可变和按位常量与概念常量。希望这有助于您的理解 - c++ function syntax/prototype - data type after brackets

【讨论】:

  • 这几乎可以回答它。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-21
  • 1970-01-01
  • 2011-03-15
  • 2011-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多