当前位置: 首页 > 知识库问答 >
问题:

要求虚函数重写使用override关键字

岳嘉石
2023-03-14

C 11添加了<code>override</code>,以确保您编写的打算重写基类虚拟函数的成员函数实际执行(或不会编译)。

但在大型对象层次结构中,有时您可能会意外地编写一个成员函数,该函数在您不打算的情况下重写基类virtual!例如:

struct A {
    virtual void foo() { }  // because obviously every class has foo().
};

struct B : A { ... };

class C : B {
private:
    void foo() {
        // was intended to be a private function local to C
        // not intended to override A::foo(), but now does
    }
};

有没有某种编译器标志/扩展至少会在< code>C::foo上发出警告?为了可读性和正确性,我只想强制所有的覆盖都使用< code>override。

共有3个答案

淳于禄
2023-03-14

我看到的-Weror=建议重写的问题是它不允许您编写以下内容:

void f() final {...}

即使这里有一个隐式的< code>override。< code >-Werror = suggest-override 不会忽略这一点(这是应该的,因为< code>override在这种情况下是多余的)

但要比那更复杂…如果你写

virtual void f() final {...}

这意味着完全不同于

virtual void f() override final {...}

第一种情况不需要覆盖任何东西!第二个有。

因此,我假设GCC检查是以这种方式实现的(即有时接受冗余的<code>override</code>),以便正确处理最后一种情况。但这并不能很好地发挥作用,例如,当final足够时,clang-time将正确删除覆盖(但GCC编译将失败…)

上官培
2023-03-14

你可以做两件事。

首先,Clang 3.5及更高版本有一个-Winconaced-noised-overide警告(由-Wall触发)。这对您的示例不太起作用,但前提是您要将空foo()覆盖{}添加到类B而不是在类C中。您实际上想要的是-Wisacing-overide,以定位所有丢失的覆盖,而不仅仅是不一致的丢失。目前没有提供,但您可能会在Clang邮件列表中投诉,他们可能会添加它。

其次,您使用Howard Hinnant的技巧将最终临时添加到基类成员函数并重新编译。然后,编译器将找到所有试图覆盖虚拟基本成员函数的进一步派生类。然后,您可以修复丢失的那些。这需要更多的工作,并且需要在类层次结构扩展时经常重新检查。

越季萌
2023-03-14

看起来GCC 5.1版本添加了我一直在寻找的警告:

-W建议-覆盖

使用 -Wsuggest-override -Werror=suggest-override 进行编译将强制所有覆盖都使用覆盖

 类似资料:
  • 未解决原始关闭原因 关键字虚拟允许派生类在需要多态的情况下覆盖,这可以在有或没有关键字覆盖的情况下关闭。添加覆盖如何影响程序? 示例代码:

  • C++中的面向对象的变成都是围绕类,继承和虚函数进行的。其中最基础的一部分就是,派生类中的虚函数会覆盖掉基类中对应的虚函数。但是令人心痛的意识到虚函数重载是如此容易搞错。这部分的语言特性甚至看上去是按照墨菲准则设计的,它不需要被遵从,但是要被膜拜。 因为覆盖“overriding”听上去像重载“overloading”,但是它们完全没有关系,我们要有一个清晰地认识,虚函数(覆盖的函数)可以通过基类

  • 关于在C中使用关键字final,我有一个问题。我知道虚函数是在基类中声明的成员函数,它应该在派生类中重写。通过动态绑定,将根据负责调用的对象的类型调用适当的方法。但是,为了防止基类中的成员函数在任何派生类中被重写,我们将使用final关键字。 为什么我们使用“最终”来防止基类中的成员函数在派生类中被覆盖,同时我们仍然必须一起使用关键字VIRTUAL(允许覆盖)。 我试图删除虚拟这个词,但我得到一个

  • 条款12:使用override声明重载函数 在C++面向对象的世界里,涉及的概念有类,继承,虚函数。这个世界最基本的概念是派生类的虚函数重写基类同名函数。令人遗憾的是虚函数重写可能一不小心就错了。给人感觉语言的这一部分设计观点是墨菲定律不是用来遵守的,只是值得尊敬的。 鉴于"重写"听起来像"重载",尽管两者完全不相关,下面就通过一个派生类和基类来说明什么是虚函数重写: class Base {

  • 我一直在使用越来越多的C11,我遇到了一些我在任何地方都找不到的东西。当我们从基指针中删除派生类时,我们需要有虚拟析构函数;但有时父析构函数需要“纯”,这在C中是不可能的。所以,我的问题是,默认值是否可以用于虚拟析构函数?我已经试过了,而且效果不错,但我不知道它是否安全,因为互联网上没有任何关于它的信息。 编辑:为了澄清这个问题,我说的是使用

  • 给定下面的代码片段,函数调用有什么不同?什么是函数隐藏?什么是函数覆盖?它们与函数重载有什么关系?两者有什么区别?我在一个地方找不到关于这些的很好的描述,所以我在这里询问,这样我可以整合信息。